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;
}

ご覧のとおり、このカーネルは、各スレッドがイメージの赤のチャネルをグローバル バッファーにコピーする 1 つのワークグループのみで動作するように作られています。
このカーネルを、6 x 6 ピクセルの画像でサイズ (2, 2) のワークグループ 1 つと呼びます。さらに、赤のチャネルのみが 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.]。
このコードを 3 つの異なるデバイス (2 つの ATI と 1 つの NVIDIA) でテストしました。すべてが同じ偽の結果を返しました。また、Python と同じことを行う小さな C プログラムを作成し、同じカーネルを呼び出して、そのときに適切な結果が返されました。だから私の間違いはpythonコードにありますが、それは私の鼻のすぐ下にあるに違いありませんが、実際には見えません。誰が何が間違っているのか考えていますか?
PS に感謝
します。私は Win7 x64、無料の EPD 7.3-2 ディストリビューション、python 2.7.3 を使用しており、このWeb サイトの pyopencl インストーラーを使用しました。

4

1 に答える 1