2013-05-08 18 views
1

在開發一個OpenCL內核時,應該計算圖像上的某些功能,但遇到了一個我無法解決的錯誤。爲了找出問題,我構建了一個仍然返回錯誤值的愚蠢的小內核。那就是:嘗試讀取image2d時使用非常微小的OpenCL內核時出現的令人費解的錯誤(使用pyopencl)

__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乘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代碼中,但我真的不能看到它,儘管它一定是在我的鼻子下面。有人知道什麼可能是錯的嗎?
謝謝
P.S.我使用的是Win7 x64,免費的EPD 7.3-2發行版,python 2.7.3,我使用了這個website的pyopencl安裝程序。

+0

,如果你硬編碼內核輸出值,會發生什麼?這會告訴你是否內核設置/執行失敗,或者讀取結果,從而縮小錯誤。 – Thomas 2013-05-08 15:36:30

回答

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]] 
…]]] 

剩下的只有05
的原因是的dstack函數返回我一個F-有序陣列。 D'oh !!
我通過複製dstack函數的結果解決了這一問題:

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

複印功能默認順序值是「C」

相關問題