OpenCL心得2
1.clEnqueueNDRangeKernel函数错误( Access violation reading location 0x000......... ) 后来发现原来是设置参数的时候搞疏忽掉了: mem = clCreateBuffer(context, CL_MEM_READ_WRITE, VectorLength, 0, err); clSetKernelArg(gpus[i].kernel, argIdx,
1.clEnqueueNDRangeKernel函数错误(Access violation reading location 0x000......... )
后来发现原来是设置参数的时候搞疏忽掉了:
mem = clCreateBuffer(context, CL_MEM_READ_WRITE, VectorLength, 0, &err);
clSetKernelArg(gpus[i].kernel, argIdx++, sizeof(cl_mem), mem);
这里的mem应当传递指针,而不是值,改成这样即可:
mem = clCreateBuffer(context, CL_MEM_READ_WRITE, VectorLength, 0, &err);
clSetKernelArg(gpus[i].kernel, argIdx++, sizeof(cl_mem), &mem);
这个问题只是疏忽和粗心导致的,而且它还不怎么好找到。
2.使用GPU所有显存资源和关于GPU寻址问题的解答
使用openCL时发现,GPU显存6GB,地址长度是32bit的,CL_DEVICE_MAX_MEM_ALLOC_SIZE是1GB,我就感到很怀疑,地址才32bit,它要如何寻址呢,怎么使用到6GB显存呢?
后经过实践发现,GPU的显存是根据上下文来分配的,也就是你需要对6GB显存创建6个上下文,每个上下文分别分配1GB内存即可。而不是在一个上下文里面分配6次1GB内存。所以说之前所怀疑的GPU寻址根本就不是个问题。当然,这个是说的理论,实际情况下你还得考虑是否有其他地方有使用显存(比如有的GPU启用ECC的情况下,会有12.5%的空间做ECC用,所以实际可以使用的空间只有87.5%),如果有的话,很明显就不可能使用所有的资源,在clEnqueueNDRangeKernel函数的时候会报CL_OUT_OF_RESOURCES错误的.
这个问题也说明的我对GPU内存模型缺少认识,当初在网上也没有找到能够说明这个的资料。最终还是自己实践来得最直接。
3.CL_MEM_OBJECT_ALLOCATION_FAILURE错误
首先得需要了解下GPU显存分配的时间。
a.当你执行clCreateBuffer函数的时候,你可以查看GPU-Z的显示,可以发现GPU的显存并没有占用。实际上你查看taskmgr,会发现内存使用却增加了。也就是执行clCreateBuffer的时候仅仅是在内存里面分配一块跟你要分配的数据一样大的内存,并且把数据Copy过去。所以这个时候他只会检查你想要分配的显存尺寸有没有超过CL_DEVICE_MAX_MEM_ALLOC_SIZE的限制,而不会去到GPU里面检查剩余空间够不够。
b.根据a你可以发现,一切显存的分配都发生在clEnqueueNDRangeKernel函数的时候,当你执行这个函数的时候,GPU的显存和使用率都起来了。也就在这个时候,如果GPU显存不够放你分配的显存的时候,问题就来了。一旦尺寸超过了,则会报CL_MEM_OBJECT_ALLOCATION_FAILURE错误,所以出现CL_MEM_OBJECT_ALLOCATION_FAILURE的时候,你应该检查clCreateBuffer创建的尺寸是否得当。