2016-11-10 181 views
1

在Opencl中,缓冲区是通过其从主机应用程序传送数据的管道。OpenCL - 缓冲区和全局内存之间的区别

cl_mem clCreateBuffer (cl_context context, cl_mem_flags flags, size_t size, 
         void *host_ptr, cl_int *errcode_ret); 

现在,如果我有一个缓冲a_buffer已检举为READ_ONLY,而内核是:

__kernel void two_buffer_double(__global float* a) 
{ 
    int i = get_global_id(0); 
    float b = a[i] * 2; 
} 

我的问题是:是a_buffer全局存储器或常量内存?我是否应该使用__constant限定符a。 cl_mem_flags(READ_ONLYREAD_WRITE)与内存限定符(globalconstant)之间的连接是什么?

+0

增加了一些关于“主机端”部分的更多信息。 –

回答

2
__constant 

限定符用于常量内存,有些卡片在纹理高速缓存中获取并从__global获得独立带宽,但其大小有限。

__global __read_only * float 

手段,OpenCL实现会尽量把它放在高速缓存(或使用一些其他的数据路径),如果硬件觉得合适,但它是__global因此仅由VRAM大小或数量的限制只是64kB的,而不是(例如)为__constant。

这些限定符用于设备端优化。

在主机端的优化,你应该用

CL_MEM_READ_ONLY 

提供其作为标志缓冲创作。这意味着设备将只读取它(可能使用一些DMA/pcie访问/缓存优化),但可以使用enqueuewrite或map unmap操作从主机端(如C#C++代码的主机,而不是设备)写入。

__constant 

适用于参数常数定义,不适用于要处理的数据。

如果编写一个过滤器的代码,数据可能是__global和滤波器掩模可以是__constant如果不能在__private存储器(其具有最终带宽)或__local存储器(比私人慢)适合所以访问掩码字节不降低数据带宽。

现在回答你的问题:

“?是a_buffer全局存储器或常量内存”

它是全球性的设备端(内核侧),因为你宣布它作为__global,但它可以在主机端(硬件)的任何地方。

编辑:主机端,取决于其它标志用于其中,例如,USE_HOST_PTR使得从系统RAM它直接可访问的,并且只有在设备侧上的虚拟缓冲器,如果没有它,并只需CL_MEM_READ_WRITE设备内存将有一个真正的缓冲区和它在RAM中的映射阴影(作为clenqueueread或clenqueuewrite的子步骤),复制将首先访问该阴影,然后上传到GPU。

一个例子设备:英特尔(R)HD(TM)在4GB DDR3L笔记本电脑的图形400:

Query           value 
CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE     65536 bytes 
CL_DEVICE_GLOBAL_MEM_CACHE_SIZE     262144 bytes 
CL_DEVICE_GLOBAL_MEM_SIZE      1636414260 bytes 

CL_DEVICE_GLOBAL_MEM_CACHE_TYPE    CL_READ_WRITE_CACHE 
CL_DEVICE_LOCAL_MEM_SIZE      65536(vs constant, benchmark it) 
CL_DEVICE_LOCAL_MEM_TYPE      CL_LOCAL(so is faster than global) 

无法查询专用内存大小,但是对于中间段游戏的AMD卡,它是256KB每个线程组。如果您为每个组设置64个线程,则每个线程可以使用4KB的寄存器空间,或者由于溢出到全局内存而变慢,因此可以使用4KB的寄存器空间(由于编译器优化)。