我正在使用 pyOpenCL 进行一些复杂的计算。它在 CPU 上运行良好,但在 NVIDIA GeForce 9400M (256 MB) 上运行时出现错误。我正在使用 Mac OS X Lion (10.7.5)
奇怪的是,这个错误并不总是出现。当我的计算使用更大的数字(导致更大的迭代)但仅在 GPU 上运行时似乎会发生这种情况。
我不写我不应该写的内存位置。通过将代码作为单个工作项运行,我排除了并发修改可能出现的问题。
我尽可能简化了我的 OpenCL 代码,并从剩下的内容中创建了一些非常简单的代码,这些代码具有非常奇怪的行为,导致pyopencl.LogicError
. 它由 2 个嵌套循环组成,其中对result
数组进行了几个赋值。这种分配甚至不需要依赖于循环的状态。shape = (1,)
这是在 GPU上的单个线程(或工作项)上运行的。
__kernel void weirdError(__global unsigned int* result){
unsigned int outer = (1<<30)-1;
for(int i=20; i--; ){
unsigned int inner = 0;
while(inner != outer){
result[0] = 1248;
result[1] = 1337;
inner++;
}
outer++;
}
}
奇怪的是,删除结果数组的任一个分配都会删除错误。此外,减小外部的初始值((1<<20)-1
例如降低到)也可以消除错误。在这些情况下,代码会正常返回,并在相应的缓冲区中提供正确的结果。在 CPU 上,它永远不会引发错误。
OpenCL 代码使用 PyOpenCL 从 Python 运行。
设置中没有什么花哨的:
platform = cl.get_platforms()[0]
device = platform.get_devices(cl.device_type.GPU)[0]
context = cl.Context([device])
program = cl.Program(context, getProgramCode()).build()
queue = cl.CommandQueue(context)
在此 Python 代码中,我将 设置result_buf
为0
,然后在 OpenCL 中运行计算,该计算将在大迭代中设置其值。之后我尝试从设备内存中收集这个值,但这就是出错的地方:
result = numpy.zeros(2, numpy.uint32)
result_buf = cl.Buffer(context, mem_flags.READ_WRITE | mem_flags.COPY_HOST_PTR, hostbuf=result)
shape = (1,)
program.weirdError(queue, shape, None, result_buf)
cl.enqueue_copy(queue, result, result_buf)
最后一行给了我:
pyopencl.LogicError: clEnqueueReadBuffer failed: invalid command queue
这种重复分配如何导致错误?
更重要的是:如何避免?
我知道这个问题可能与平台有关,因此可能难以重现。但这是我唯一可以访问的机器,所以代码应该可以在这台机器上运行。
免责声明:我以前从未使用过 OpenCL(或 CUDA)。我在 GPU 不支持 OpenCL 的机器上编写代码。我总是在 CPU 上测试它。现在我切换到 GPU,我发现错误不会持续发生令人沮丧,我不知道为什么。