Opencl 为什么clCreateBuffer使用主机内存? < >我使用C++包装器并创建缓冲区,使用以下代码: cl_int err(0); unsigned int size; void *data = GetData(/*out*/ size); cl::Buffer buf(m_ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, size, data, &err); free(data);

Opencl 为什么clCreateBuffer使用主机内存? < >我使用C++包装器并创建缓冲区,使用以下代码: cl_int err(0); unsigned int size; void *data = GetData(/*out*/ size); cl::Buffer buf(m_ctx, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, size, data, &err); free(data);,opencl,gpu,Opencl,Gpu,之后,我的应用程序的工作集增加了大小字节。由于我有32位的应用程序,我不能分配超过1.5 Gb的总容量,但GPU有3 Gb 是否可以分配更多缓冲区 PS.大小小于128 Mb 更新:我只使用1个设备,它是GPU。(GeForce GTX 780 GPU NVIDIA Corporation 337.88)部分回答您的问题。可分配的最大内存块大小: cl_ulong max_buffer_size = 0; cl_int ret_code = clGetDeviceInfo(Device, CL

之后,我的应用程序的工作集增加了
大小
字节。由于我有32位的应用程序,我不能分配超过1.5 Gb的总容量,但GPU有3 Gb

是否可以分配更多缓冲区

PS.
大小
小于128 Mb


更新:我只使用1个设备,它是GPU。(GeForce GTX 780 GPU NVIDIA Corporation 337.88)

部分回答您的问题。可分配的最大内存块大小:

cl_ulong max_buffer_size = 0;

cl_int ret_code = clGetDeviceInfo(Device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, 
    sizeof(cl_ulong), &max_buffer_size, NULL);

if(ret_code != CL_SUCCESS){
    fprintf(stderr, "Error %d happened \n", ret_code);
}

通常,OpenCLAPI不允许分配大的(超过数百兆字节)内存对象

DarkZeros的评论是正确的。它似乎取决于实现,当我使用
clEnqueueWriteBuffer()
而不是flag
CL\u MEM\u COPY\u HOST\u PTR
时,它解决了问题

我不知道问题发生的确切原因,可能是一些潜在的驱动程序行为

然而,禁用特殊标志似乎可以解决nVIDIA平台的问题,AMD也可能如此。所以我写了一个正确的答案

cl_int err(0);
unsigned int size;
void *data = GetData(/*out*/ size);   

cl::Buffer buffer = cl::Buffer buf(m_ctx,  CL_MEM_READ_WRITE, 
      size, NULL, &err);
err = queue.EnqueueWriteBuffer(buffer, CL_TRUE, NULL, size, data);

free(data); 

我不得不问:是不是您有多个平台和/或设备,并且意外地选择了CPU作为要处理的设备(而不是GPU)?
CL\u MEM\u COPY\u HOST\u PTR
可能会触发某些固定行为。禁用它而使用正常的
clEnqueueWriteBuffer()
可能会解决问题。如果没有,那么这就是驱动程序在较低级别的工作方式,可能不可能改变行为。@DarkZeros通常,
CL\u MEM\u COPY\u HOST\u PTR
不应该导致钉住(与
CL\u MEM\u USE\u HOST\u PTR
相反),但您可能比我更了解细节,而且有疑问,行为取决于OpenCL实现。(至少,规范中可能没有任何东西阻止实现固定内存…@Marco13是的,它不应该导致固定内存。但该标准并没有准确定义固定内存的工作方式,nVIDIA/AMD的工作方式也有所不同。我的猜测是,无论你做什么,驱动程序都会在主机端为垃圾处理操作分配内存,即使它没有被固定,这是很不幸的,它无法从用户端修复。@在某种程度上,暗零可能:在这种特殊情况下,应该可以简单地在设备上分配内存,然后用
clEnqueueWriteBuffer
复制它,手动管理主机端…我不分配巨大的内存对象,我分配许多小对象。好的,我知道了。在总共1.5 Gb之后,您是否收到任何特定的错误/异常?没有,我只是没有更多的内存来分配进程。但是,当我使用
clEnqueueWriteBuffer()
绕过这个限制时,我得到了BSOD=(。这肯定是一个bug。API应该通过clCreateBuffer或clCreateImage调用返回CLU OUT资源。