Fra*_*ter 17 memory-management opencl
我在教程中看到了两个版本,但我无法找到它们的优点和缺点.哪一个是正确的?
cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DATA_SIZE, NULL, NULL);
clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, inputdata, 0, NULL, NULL);
Run Code Online (Sandbox Code Playgroud)
与
cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ,sizeof(float) * DATA_SIZE, inputdata, NULL);
Run Code Online (Sandbox Code Playgroud)
谢谢.
[更新]
我添加CL_MEM_COPY_HOST_PTR,到第二个示例以使其正确.
小智 9
在我使用OpenCL期间,我发现了一个非常重要的区别
cl_mem CT = clCreateImage3DContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR , Volume_format, X, Y, Z, rowPitch, slicePitch, sourceData, &error);
Run Code Online (Sandbox Code Playgroud)
和
cl_mem CT = clCreateImage3D(Context, CL_MEM_READ_ONLY , Volume_format, X, Y, Z, 0, 0, 0, &error);
error = clEnqueueWriteImage(CommandQue, CT, CL_TRUE, origin, region, rowPitch, slicePitch, sourceData, 0, 0, 0);
Run Code Online (Sandbox Code Playgroud)
对于第一种方法,OpenCL将主机指针复制到GPU而不是直接复制.首先,它会在主机上分配第二个临时缓冲区,如果你把像CT这样的大东西加载到GPU上会导致问题.在短时间内,所需的内存是CT大小的两倍.此功能也不会复制数据.它在参数设置期间被复制到使用3D图像对象的内核函数.
第二种方法直接将数据复制到GPU.OpenCL没有进行额外的分配.我认为这对于普通缓冲对象可能是相同的.
我假设inputdata不是NULL.
在这种情况下,第二种方法根本不起作用,因为规范说,clCreateBuffer返回NULL并且出现错误,如果:
CL_INVALID_HOST_PTR如果host_ptr为NULL并且在标志中设置了CL_MEM_USE_HOST_PTR或CL_MEM_COPY_HOST_PTR,或者如果host_ptr不为NULL但未在标志中设置CL_MEM_COPY_HOST_PTR或CL_MEM_USE_HOST_PTR.
所以你的意思是
clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);
Run Code Online (Sandbox Code Playgroud)
要么
clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);
Run Code Online (Sandbox Code Playgroud)
第一个应该与您展示的第一个方法大致相同,而第二个实际上不会复制数据,而是使用提供的内存位置进行缓冲存储(在设备内存中缓存部分或全部) .这两者中哪一个更好取决于使用场景.
Personaly我更喜欢使用首先分配缓冲区的两步方法,然后用writeToBuffer填充它,因为我发现更容易看到发生了什么(当然一步可能更快(或者它可能不会,这只是猜测))