2011-09-06 104 views
3

我有一个尺寸为512 x 512 x 512的图像。 我需要单独处理所有体素。 我如何获得线程ID来做到这一点? 如果我使用1D线程ID块的数量将超过65536三维图像索引

int id = blockIdx.x*blockDim.x + threadIdx.x; 

注: - 我对3D卡犯规支撑格栅

回答

6

您可以在CUDA 4.0和计算能力2.0+中使用3D标记。示例代码:

int blocksInX = (nx+8-1)/8; 
int blocksInY = (ny+8-1)/8; 
int blocksInZ = (nz+8-1)/8; 

dim3 Dg(blocksInX, blocksInY, blocksInZ); 
dim3 Db(8, 8, 8); 
foo_kernel<<Dg, Db>>(R, nx, ny, nz); 

... 

__global__ void foo_kernel(float* R, const int nx, const int ny, const int nz) 
{ 
    unsigned int xIndex = blockDim.x * blockIdx.x + threadIdx.x; 
    unsigned int yIndex = blockDim.y * blockIdx.y + threadIdx.y; 
    unsigned int zIndex = blockDim.z * blockIdx.z + threadIdx.z; 

    if ((xIndex < nx) && (yIndex < ny) && (zIndex < nz)) 
    { 
    unsigned int index_out = xIndex + nx*yIndex + nx*ny*zIndex; 
    ... 
    R[index_out] = ...; 
    } 
} 

如果您的设备不支持计算能力2.0,有一些窍门:

int threadsInX = 16; 
int threadsInY = 4; 
int threadsInZ = 4; 

int blocksInX = (nx+threadsInX-1)/threadsInX; 
int blocksInY = (ny+threadsInY-1)/threadsInY; 
int blocksInZ = (nz+threadsInZ-1)/threadsInZ; 

dim3 Dg = dim3(blocksInX, blocksInY*blocksInZ); 
dim3 Db = dim3(threadsInX, threadsInY, threadsInZ); 

foo_kernel<<<Dg, Db>>>(R, nx, ny, nz, blocksInY, 1.0f/(float)blocksInY); 

__global__ void foo_kernel(float *R, const int nx, const int ny, const int nz, 
          unsigned int blocksInY, float invBlocksInY) 
{ 

    unsigned int blockIdxz = __float2uint_rd(blockIdx.y * invBlocksInY); 
    unsigned int blockIdxy = blockIdx.y - __umul24(blockIdxz, blocksInY); 
    unsigned int xIndex = __umul24(blockIdx.x, blockDim.x) + threadIdx.x; 
    unsigned int yIndex = __umul24(blockIdxy, blockDim.y) + threadIdx.y; 
    unsigned int zIndex = __umul24(blockIdxz, blockDim.z) + threadIdx.z; 

    if ((xIndex < nx) && (yIndex < xIndex) && (zIndex < nz)) 
    { 
     unsigned int index = xIndex + nx*yIndex + nx*ny*zIndex; 
     ... 
     R[index] = ...; 
    } 

} 
+0

你好,谢谢你的信息,但对于3D网格我的卡犯规支持.. :-( – user570593

+0

有一些技巧使用二维一个模拟3D网格,看到我的编辑答案。 – MeinLieberTanz

+0

非常感谢你... – user570593

1

你可以使用网格。它给你更多的索引。

1

如果您需要更大的网格,CUDA支持所有硬件上的2D网格,并且最新版本的CUDA工具包也支持当前Fermi硬件上的3D网格。

但是,并不是必须拥有这样大的网格。如果每个体素操作是独立的,那么为什么不使用一维网格,而是让每个线程处理多个体素?这样的方案不仅不需要更大的2D或3D网格,它可能更有效,因为与块的调度和初始化相关的固定成本可以在多个体素计算中分摊。

1

注意你的电脑的内存是不是3D。这只是可视化问题,所以您可以将3D图像转换为单个指针。

Array[i][j][z] is same as Array2[ i*cols+j + rows*cols*z]; 

现在喂数组2到CUDA和单维工作

0

我以前是这样的:

在代码中定义网格: 为dim3 altgrid,altthreads; altgrid.x = lx; altgrid.y = ly; altgrid.z = 1; altthreads.x = lz; altthreads.y = 1; altthreads.z​​ = 1;

和在内核

int idx = threadIdx.x; 
int idy = blockIdx.x ; 
int idz = blockIdx.y ; 

由于在装置的阵列是唯一1D你通过一个矩阵A的检索[IDX] [IDY] [IDZ]元素作为A [IND],其中IND = IDZ + LZ *(IDY + LY * IDX);

我希望它能帮助