2011-06-01 61 views
1

我試圖從給定的CUDA偏移量計算blockIdx.x和blockIdx.y,但我完全被大腦阻塞。這個想法是在可能的情況下從共享內存讀取數據,在其他情況下是從全局內存中讀取數據從給定的二維偏移量知道CUDA中的塊ID

在例如,如果我已經64個元件一維陣列和我配置具有16X1螺紋的內核(總共4個塊),每個線程可以使用訪問的位置:

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

,我可以容易從IDX得到一個給定的索引值的blockIdx.x作爲

int blockNumber = idx/blockDim.x; 

但與8×8元素和4×4的線程的內核配置(2×2塊總共)二維場景每個線程使用訪問的位置:

int x = threadIdx.x + blockIdx.x * blockDim.x; 
int y = threadIdx.y + blockIdx.y * blockDim.y; 
int pitch = blockDim.x * gridDim.x; 
int idx = x + y * pitch; 

int sharedMemIndex = threadIdx.x+threadIdx.y+BLOCK_DIM_X; 
__shared_block[sharedMemIndex] = fromGlobalMemory[idx]; 
__syncthreads(); 

// ... some operations 

int unknow_index = __shared_block[sharedMemIndex]; 

if (unknow_index within this block?) 
    // ... read from shared memory 
else 
    // ... read from global memory 

我該如何知道給定idx上的Block ID.x和ID.y?即索引34和35在塊(1,1)中的塊(0,1)和索引36中。因此,如果塊(0,1)中的線程讀取索引35的值,該線程將知道該值位於其塊中,並將從共享內存中讀取該值。索引35值將被存儲在塊的共享存儲器的位置11(0.1)中。

在此先感謝!

+0

我根本不理解這個問題。任何內核中的任何線程都始終具有blockIdx。{xyz}可用。爲什麼你需要嘗試和計算它? – talonmies 2011-06-01 16:17:56

+0

您需要從內存中執行一些加載操作。第一個負載value_index_1 = array [idx],第二個負載value_index_2 = array [value_index]。所以,如果value_index_1在塊中,我可以從共享內存加載,否則我需要從全局內存加載。 – pQB 2011-06-01 16:42:15

+0

您仍然不需要爲其計算塊索引值。您可以比較塊中給定線程ID和塊大小與全局線程ID和索引的差異。這會告訴你索引是否在塊內共享內存的範圍內。 – talonmies 2011-06-01 18:12:01

回答

1

在實踐中,我實在想不出一個很好的理由,這是以往任何時候都需要的,但你可以計算出這樣的結果,對於任意索引值idx(假設列排序索引):

int pitch = blockDim.x * gridDim.x; 
int tidy = idx/pitch; // div(idx,pitch) 
int tidx = idx - (pitch * tidy); // mod(idx,pitch) 
int bidx = idx/blockDim.x; 
int bidy = idy/blockDim.y; 

它應該爲您提供bidx和bidy中索引的塊座標。

+0

這就像我在找:)但它不工作。在8×8元素的2D陣列的示例中,塊大小爲4×4並且網格大小爲2×2 .-索引35在塊(0,1)中並且在塊(1,1)中在索引36中。通過這些操作,指數35和36在區塊(2,2)中。 我除了在bidx = 0和bidy = 1中找到索引= 35之外。我爲這個問題添加了更多的細節。 – pQB 2011-06-03 07:36:57

+0

對不起,最後兩行有錯誤。全球(x,y)指數應除以區塊維度而不是網格維度。編輯來解決這個問題。 – talonmies 2011-06-03 08:06:39

+0

這就像我正在尋找:)但它不工作。不應該是 bidx = tidx/blockDim.x bidy = tidy/blockDim.y ?謝謝! – pQB 2011-06-03 08:06:42

0

您正在執行不必要的計算。

idx/blockDim.x 
-->(blockDim.x * blockIdx.x + threadIdx.x)/blockDim.x 
-->(blockIdx.x + threadIdx.x/blockDim.x) 
--> blockIdx.x + 0 (threadIdx.x always less than blockDim.x) 

您可以使用blockIdx.x代替卷積計算。 2D網格也是如此(blockIdx.x和blockIdx.y)。

+0

你好Pavan,謝謝你的回答,但我不知道該怎麼處理它:)。問候! – pQB 2011-06-03 07:47:29

1

有沒有必要應用Idx的數學來找出X和Y塊或從Idx向後查找塊索引。對於每個線程(Idx),只需調用blockIdx.xblockIdx.y即可找出Y和X塊。

在內核中的任何一點:

int x = blockIdx.x // will give you X block Index at that particular thread 
int y = blockIdx.y // will give you Y block Index at that particular thread. 

更新: 如果你在反向操作死心塌地,你需要知道的間距和塊尺寸的值

int currentRow = idx/pitch; 
    int currentCol = idx%pitch; 

    int block_idx_x = currentCol/blockDim.x; 
    int block_idx_y = currentRow/blockDim.y; 
+0

你好Jawad,謝謝你的答案,但我正在尋找一種方法來計算這些值在給定的索引,而不使用blockIdx.x和blockIdx.y。這是一個逆向操作。問候! – pQB 2011-06-03 07:48:43

+0

我不明白你的觀點。當您使用相同的(blockIdx.x和blockIdx.y)來計算Idx本身時,您希望從Idx中找到blockIdx.x和blockIdx.y。無論如何,如果你想知道落後的數學,請參閱我的回答中的更新 – jwdmsd 2011-06-03 08:00:16

+0

是的,我注意到這個問題有點含糊。我已經更新了它,以顯示索引不是從blockIdx.x和blockIdx.y – pQB 2011-06-03 08:12:11

相關問題