2011-06-01 62 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

相关问题