AMD编程手册小译

5.5.3 Memory Allocation

5.5.3.1 使用CPU

    使用CL_MEM_ALLOC_HOST_PTR创建内存对象,并使用map以及unmap操作,不要使用read/write。原因是如果内存对象是使用CL_MEM_ALLOC_HOST_PTR创建的,内核将运行在应用创建的缓存上(所有的供应商都是这样处理的)。这就使得CPU和应用之间的缓存是零拷贝(Zero Copy);内核可以直接更新应用的缓存,在这种情形下map/unmap是一个空操作(no-op)。同时,当在宿主机上分配内存时,需要保证内存的正确对齐。例如,一个使用float4*的缓存,必须保证128bit对齐。

5.5.3.2 使用CPU和GPU设备或者使用一个APU设备

   当创建内存对象时,使用CL_MEM_USE_PERSISTENT_MEM_AMD。这启动了零拷贝特性。参见5.5.3.1

5.5.4 Mapping

    宿主机程序可以使用clEnqueueMapBuffer/clEnqueueMapImage来获取内存对象数据的一个指针。当使用完毕后,必须使用clEnqueueUnmapMemObject让内核重新可以使用内存对象。当一个内存对象是存储在设备上时,数据既可以从宿主机传输过来也可以相反,亦或者直接从宿主机访问这个内存对象。当一个内存对象是存储在宿主机上面时,或者存储在设备上,但可以被宿主机直接访问,这个内存对象可以采用零拷贝的方式。数据将不会被传输,而是被宿主机和设备直接访问。5.2描述了各种情况。

5.5.4.1 零拷贝内存对象

    CL_MEM_USE_PERSISTENT_MEM_AMD,CL_MEM_USE_HOST_PTR以及CL_MEM_ALLOC_HOST_PTR支持零拷贝内存对象。第一个提供了驻留在设备上的内存对象零拷贝,其余两个提供了驻留在宿主机上的零拷贝。
    零拷贝内存而已用来优化应用中的数据移动。当clEnqueMapMapBuffer/clEnqueueMapImage /clEnqueueUnmap Object使用时,将没有任何运行时传输发生。这时操作将非常快;然而,在运行时每次调用映射得到的主机端指针的值可能不同。另外需要注意的是对于图像对象只有在创建时使用CL_MEM_USE_PERSISTENT_MEM_AMD才能够实现零拷贝。
    从Southern Island开始,设备就开始支持在Linux下的零拷贝操作。但是CL_MEM_USE_PERSISTENT_MEM_AMD必须在创建图像对象时使用才能够支持零拷贝。
    当宿主机内存被设备以稀少的方式访问时或者当较大的宿主机内存被多个设备所共享并且内存拷贝非常昂贵时,采用零拷贝的方式访问宿主机内存对象可以获得性能的提升。当选择这种方式时,要确保传输的代价比慢速的访问代价要高。(译者注:因为如果传输量过小,可能PCIE的数据访问会慢于数据传输,也就反而可能降低性能。)
    通过宿主机以流的形式写入支持零拷贝的设备内存区域与数据的传输速率相同,所以,当宿主机不需要读取内存对象时,这种方式可以避免主机端需要内存对象的一次拷贝所带来的传输损失。同时,对于在内核执行过程中需要部分更新的内存对象,也会从中获得益处。如果内存区必须要宿主机进行读取,使用clEnqueueCopyBuffer来传输数据到一个CL_MEM_ALLOC_HOST_PTR的内存区域上。

5.5.4.2 复制内存对象

    当内存对象是在设备中,当主机端调用clEnqueueMapBuffer/clEnqueueMapImage/clEnqueueUnmapMemObject被调用时,如果内存对象采用拷贝映射的方式,数据将在主机和设备之间传输(to and from)。表5.3定义了map_flags参数如何影响传输效果。在运行时传输的部分仅仅是参数中offset以及cb请求的那部分内存对象。当只访问内存对象的一部分时,只映射该部分可以提高性能。

AMD编程手册小译_第1张图片
    对于默认的内存对象,由clEnqueueMapBuffer/clEnqueueMapImage可能对于相同的内存区域返回的指针不同,这是因为每次调用都可能使用不同的运行时缓存。
    对于使用CL_MEM_USE_HOST_PTR以及CL_MEM_ALLOC_HOST_PTR那么对于所有的映射操作,返回的都是相同的位置,返回的指针指向的也都是相同的内存区域。对于其他的拷贝内存对象,返回的指针则可能不是指向同一个内存区域。
    对于使用CL_MEM_USE_HOST_PTR,clCreateBuffer/clCreateImage将固定宿主机内存并传给host_ptr参数。当内存对象被删除时,这块内存也将解固定。为了最小化固定开销,将内存以4KB进行对齐,这将防止在运行过程中在每次map/unmap中都需要pin/unpin操作,但是会增加pinned内存。
    对于使用CL_MEM_USE_HOST_PTR,作为参数传递到clCreateBuffer/clCreateImage的主机端内存指针将作为map的地址。正如在5.5.1.1所述,主机端内存传输在每次传输中的pinning/unpinning操作会造成可观的损失。如果使用,则需要保证内核中的内存对于数据类型大小来讲是对齐的。如果主机端的内存需要进行更新,那么最好使用CL_MEM_COPY_HOST_PTR替换CL_MEM_ALLOC_HOST_PTR标志。相反如果需要更新设备内存,则使用CL_MEM_USE_PERSISTENT_MEM_AMD以及使用clEnqueueWriteBuffer。
    如果CL_MEM_COPY_HOST_PTR与CL_MEM_ALLOC_HOST_PTR在创建内存时共同使用,那么内存区域将会固定到主机端并且使用传输的数据进行初始化。而对于其他的内存对象,推迟申请意味着内存并没有在设备上创建,所以在运行时,首先需要将内存数据复制到一个临时的存储区域。当设备第一次访问这个内存对象时,它才会被创建。这时,需要传输的数据将会被拷贝。例如,当使用CL_MEM_COPY_HOST_PTR创建内存对象时。不推荐使用CL_MEM_COPY_HOST_PTR来创建内存,因为这样会导致额外的内存拷贝操作。相反,采用非CL_MEM_COPY_HOST_PTR来创建内存对象,并用clEnqueueWriteBuffer/clEnqueueWriteImage进行初始化。(这点需要注意)。

    当传输图像时,会有额外的开销,是因为图像数据在传输中需要转换成线性地址供宿主机访问。运行时通过在设备上执行内核实现此功能。
(好了,先翻译两小节,英语水平一般。如果有错误欢迎指出。)
    


你可能感兴趣的:(OpenCL,GPU)