1

在开发一个应该计算图像上某些特征的 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 安装程序。

4

1 回答 1

1

好的,我发现出了什么问题....愚蠢的我。所以,如果有人像我一样心不在焉,这里是解决方案:
正如托马斯建议的那样,我测试了“阅读部分”,它返回了预期的结果。
我还用 cl.enqueue_read_image 读回了图像。结果是错误的,但解释了我第一次得到的值。我有类似的东西:

[[[ 0  6 12 18]
  [24 30  1  7]
  [13 19 25 31]
  [ 2  8 14 20]
  [26 32  3  9]
  [15 21 27 33]]

 [[ 4 10 16 22]
  [28 34  5 11]
  [17 23 29 35]
  [ 0  0  0  0]
  [ 0  0  0  0]
  [ 0  0  0  0]]
…]]]

剩下的只有0。
原因是dstack函数返回给我一个F-ordered数组。哦!!
我通过复制 dstack 函数的结果解决了这个问题:

img = np.dstack((arr, np.zeros((arr.shape[0], arr.shape[1], 3), dtype=np.uint8))).copy()

复制功能的默认顺序值为“C”

于 2013-05-10T09:40:43.113 回答