2013-07-05 67 views
0

我的任務是使用CUDA實現圖像重建算法代碼。我爲C提供了相同的代碼。輸入到代碼是一個DAT文件,它包含大小爲360倍的圖像640×480.The碼是這樣的:CUDA中的圖像序列處理

FILE *in,*out; 
    float *i_data,*o_data; 
    i_data=(float *)malloc(mem_size); 
    for(int projection=0;projection<360;projection++) 
    { 
     in=fopen("filename.dat","rb"); 
     fread(i_data,mem_size,1,in); 
     ... some math ... 
     for(int slice_no=-240;slice_no<240:slice_no++) 
     { 
      for (i=-320;i<320;i++) 
      for (j=-320;j<320;j++) 
      { 
      // do some operations 
      (*(o_data*slice_no)+(j+320)+(i+240))+=(*(i_data*value)+(j+240)+(i+320)); 
      // some more math 
      } 
     } 
    } 

輸出浮子指針寫回dat文件。如果我必須並行化這些循環,那麼我將如何在CUDA中做到這一點?我嘗試使用640個線程的640個塊來實現CUDA中的內循環。我如何將線索引給循環內的指針操作。我試過

但是這會在輸出指針中給出錯誤的值。大部分是NAN。除了上面代碼片段中顯示的指針行外,我能夠成功實現其他數學運算。

任何人都可以請幫我這麼做嗎?我在這段代碼中做錯了什麼? 也有可能在這裏並行化所有for循環?

+0

我看不出有人能告訴你你在做什麼錯在這段代碼中。你所顯示的代碼,即'i'和'j'的賦值,以及(不完整的)內核調用都是微不足道的,並不代表你正在做什麼。 –

+0

@RobertCrovella:我想我已經發現我做錯了什麼。 cudaMalloc給float數組賦予了隨機值。這是造成問題的原因。你可以幫助我如何初始化cudaMalloc之後的浮點數組。我檢查了這個答案[鏈接](http://stackoverflow.com/questions/10589925/initialize-device-array-in-cuda)。但是這只是爲了我猜。你能告訴如何初始化float數組爲零。 – Dhivya

回答

0

限制內循環在單個塊內運行效率不高。此外,如果並行化所有三個循環(或者如果您可以從磁盤加載更多數據並同時將許多圖像發送到GPU),您將獲得更多好處。

您的問題,看起來像

for(x = minx; x < maxx; ++x) 
{ 
    for(y = miny; y < maxy; ++y) 
    { 
    for(z = minz; z < maxz; ++z) 
    { 
     // do some math 
    } 
    } 
} 

線程的內核數量應該是:

num_thread = (maxx-minx) * (maxy-miny) * (maxz-minz); 

你應該獨立於塊的大小。將其設置爲像blockDim.x = 256(嘗試找到更好的常量)的常量。

塊的數量將是

gridDim.x =(num_thread + blockDim.x)/blockDim.x 

請注意,我推理,如果三個環路被展開成一個大圈,但你可以讓2D和3D甚至線程塊,如果你的驅動程序,允許它。

在你的內核,從內置的變量,你可以計算展開大循環內的全球指數

int index = blockIdx.x * blockDim.x + threadIdx.x 

確保你沒有超出範圍

if(index >= num_thread) return; // do nothing 

現在,使用index可以恢復xyzslice_noij)作爲

x = index/((maxy-miny) * (maxz-minz)) + minx; 
y = (index % ((maxy-miny) * (maxz-minz)))/(maxz-minz) + miny; 
z = (index % ((maxy-miny) * (maxz-minz))) % (maxz-minz) + minz; 
+0

謝謝你的回覆。我會嘗試實現這一點。你能解釋一下「我和j必須從一維值blockIdx.x * blockDim.x + threadIdx.x計算」對不起,我不知道該怎麼做。假設我設置640個線程的640個塊,我如何在內核中設置i和j值。 – Dhivya

+0

@Dhivya想象一下2D C數組「int A [H] [W]」。 「A [i] [j]」相當於「((int *)A)[k]」,例如「k = i * W + j」。從「k」可以恢復「i = k/W」和「j = k%W」。我的答案中的3D「x」,「y」和「z」是使用相同的推理從1D索引計算得出的 –

+0

感謝您的解釋。我實施了這個,但重建很慢。你能告訴我一些提高速度的方法嗎?我閱讀共享內存和紋理內存。但我不明白如何爲這些嵌套for循環實現它。 – Dhivya