3D图像索引

时间:2011-09-06 09:51:10

标签: cuda

我有一张尺寸为512 x 512 x 512的图片。 我需要单独处理所有体素。 如何获取线程ID来执行此操作? 如果我使用1D线程ID,则块数将超过65536。

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

注意: - 我的卡不支持3D网格

5 个答案:

答案 0 :(得分:6)

您可以在CUDA 4.0中使用3D索引并计算2.0+的能力。示例代码:

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] = ...;
    }

}

答案 1 :(得分:1)

你可以使用网格。它为您提供了更多的索引。

答案 2 :(得分:1)

请注意,PC的内存不是3D内存。这只是可视化的问题,因此您可以将3D图像转换为单个指针。

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

现在将Array2提供给CUDA并以单维方式工作

答案 3 :(得分:0)

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

然而,拥有如此大的网格并非绝对必要。如果每个体素操作都是独立的,那么为什么不使用一维网格,而是让每个线程处理一个以上的体素?这样的方案不仅不需要更大的2D或3D网格,而且可能更有效,因为与块的调度和初始化相关的固定成本可以通过多个体素计算进行摊销。

答案 4 :(得分: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) ;

我希望它有所帮助