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创建的尺寸是否得当。