在开发一个应该计算图像上某些特征的 OpenCL 内核时,我遇到了一个我无法解决的错误。为了解决这个问题,我构建了一个愚蠢的、微小的内核,它仍然返回错误的值。这里是:
__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE |
CLK_ADDRESS_CLAMP_TO_EDGE |
CLK_FILTER_NEAREST;
__kernel void readImageTest(__read_only image2d_t img, __global float *result){
const int2 coord = (int2)(get_local_id(0), get_local_id(1));
int2 nbOfWorkers = (int2)(get_local_size(0), get_local_size(1));
uint4 tmp = read_imageui(img, sampler, coord);
result[coord.x + coord.y * nbOfWorkers.x] = (float)tmp.x;
}
如您所见,该内核仅适用于一个工作组,其中每个线程将图像的红色通道复制到全局缓冲区中。
我在 6 x 6 像素的图像上使用 1 个大小为 (2, 2) 的工作组调用此内核。此外,只有红色通道包含不同于 0 的值。这些值从 0 到 35,左上角像素的红色值设置为 0,其右邻像素为 1,依此类推,直到右下角像素的红色值值设置为 35。以下是一些 Python 代码片段:
def test_read_img(self):
arr = np.array(range(0, 36), dtype=np.uint8).reshape((6, 6))
img = np.dstack((arr, np.zeros((arr.shape[0], arr.shape[1], 3), dtype=np.uint8)))
result = self.detector.read_img(img, (2, 2))
检测器是处理 OCL 调用的类的一个实例,这里是 *read_img* 函数:
def read_img(self, image, local_size):
cl_image = cl.Image(self.ctx,
self.mf.READ_ONLY | self.mf.COPY_HOST_PTR,
self.cl_img_format,
image.shape[1::-1],
None,
image)
out_buf = cl.Buffer(self.ctx, self.mf.WRITE_ONLY,
size=int(local_size[0] * local_size[1] * dtype('float32').itemsize))
self.prog.readImageTest(self.queue, local_size, local_size, cl_image, out_buf)
result = zeros(local_size[0] * local_size[1], float32)
cl.enqueue_copy(self.queue, result, out_buf).wait()
return result
最后是如何实例化变量 *cl_image_format* :
self.cl_img_format = cl.ImageFormat(cl.channel_order.RGBA,
cl.channel_type.UNSIGNED_INT8)
因此,如果一切正常,结果应该是 [0. 1. 6. 7.] 而不是我得到 [0. 24. 4. 28.]。
我在三个不同的设备上测试了这段代码:2 个 ATI 和 1 个 NVIDIA。全部返回相同的错误结果。我还制作了一个小型 C 程序,它执行与 python 相同的操作并调用相同的内核,这一次返回了正确的结果。所以我的错误出在python代码中,但我真的看不到它,尽管它一定就在我的眼皮底下。有人知道可能出了什么问题吗?
谢谢
PS 我使用的是 Win7 x64,免费的 EPD 7.3-2 分发版,python 2.7.3,我使用了这个网站上的 pyopencl 安装程序。