OpenCL - 缓冲区和全局内存之间的区别

时间:2016-11-10 10:02:51

标签: opencl constants global

在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)之间的联系是什么?

1 个答案:

答案 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,如果不能适合__private内存(具有最终带宽)或__本地内存(慢于私有),则过滤掩码可能是__constant,因此访问掩码字节不会减少数据带宽。

现在回答您的问题:

  

" a_buffer是全局内存还是常量内存? "

它是设备端(内核端)的全局,因为您将其声明为__global,但它可能位于主机端(硬件)的任何位置。

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

示例设备:4GB DDR3L笔记本电脑中的英特尔(R)HD(TM)GRAPHICS 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寄存器空间或其中一半(由于编译器优化),然后因为溢出到全局内存而变慢。