Arrays cuda中的动态3D数组参数

Arrays cuda中的动态3D数组参数,arrays,cuda,Arrays,Cuda,我试图在cuda的内核函数中使用动态3D数组参数,但做得不好 __global__ void kernel ( 3D array pointer ) { // do something } int main() { const int NUM_OF_ARRAY; const int ROW; const int CAL; int arr[NUM_OF_ARRAY][ROW][CAL]; // Maybe I should use cudaMalloc

我试图在cuda的内核函数中使用动态3D数组参数,但做得不好

__global__ void kernel ( 3D array pointer )
{
// do something
}

int main()
{
    const int NUM_OF_ARRAY;
    const int ROW;
    const int CAL;

    int arr[NUM_OF_ARRAY][ROW][CAL]; 
    // Maybe I should use cudaMalloc3D or cudaMalloc3DArray

    dim3 grid( , , ,);
    dim3 block( , , , );

    kernel <<< grid, block >>> ( ? );
 }
我看到了罗伯特的答案,但我认为我的情况有点不同

若数组的行和cal是在运行时确定的,那个么我如何在cuda中分配那个内存,并将其指针指定给内核函数呢

我试着使用Cudamaloc3d或Cudamaloc3d,但我不能很好地使用,因为我以前从未使用过

有人能用动态3D数组参数演示一个简单的例子吗


这对我会有帮助的。谢谢。

鉴于前面链接的答案和其他地方提出的所有原因,这不一定是处理3D阵列的好方法。更好的方法是将数组展平,并使用指针算法模拟3D访问

但为了证明前面的示例实际上不需要硬编码维度,下面的示例经过修改以显示变量运行时维度的用法:

#include <iostream>

inline void GPUassert(cudaError_t code, char * file, int line, bool Abort=true)
{
    if (code != 0) {
        fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code),file,line);
        if (Abort) exit(code);
    }
}

#define GPUerrchk(ans) { GPUassert((ans), __FILE__, __LINE__); }



  __global__ void doSmth(int*** a, int sz_x, int sz_y, int sz_z) {
    for(int i=0; i<sz_z; i++)
     for(int j=0; j<sz_y; j++)
      for(int k=0; k<sz_x; k++)
       a[i][j][k]=i-j+k;
 }
 int main() {

  unsigned sx;
  unsigned sy;
  unsigned sz;
  std::cout << std::endl << "Enter x dimension (3rd subscript): " ;
  std::cin >> sx;
  std::cout << std::endl << "Enter y dimension (2nd subscript): " ;
  std::cin >> sy;
  std::cout << std::endl << "Enter z dimension (1st subscript): " ;
  std::cin >> sz;

  int*** h_c = (int***) malloc(sz*sizeof(int**));
  for(int i=0; i<sz; i++) {
   h_c[i] = (int**) malloc(sy*sizeof(int*));
   for(int j=0; j<sy; j++)
    GPUerrchk(cudaMalloc((void**)&h_c[i][j],sx*sizeof(int)));
  }
  int ***h_c1 = (int ***) malloc(sz*sizeof(int **));
  for (int i=0; i<sz; i++){
    GPUerrchk(cudaMalloc((void***)&(h_c1[i]), sy*sizeof(int*)));
    GPUerrchk(cudaMemcpy(h_c1[i], h_c[i], sy*sizeof(int*), cudaMemcpyHostToDevice));
    }
  int*** d_c;
  GPUerrchk(cudaMalloc((void****)&d_c,sz*sizeof(int**)));
  GPUerrchk(cudaMemcpy(d_c,h_c1,sz*sizeof(int**),cudaMemcpyHostToDevice));
  doSmth<<<1,1>>>(d_c, sx, sy, sz);
  GPUerrchk(cudaPeekAtLastError());
  int res[sz][sy][sx];
  for(int i=0; i<sz; i++)
   for(int j=0; j<sy; j++)
    GPUerrchk(cudaMemcpy(&res[i][j][0], h_c[i][j],sx*sizeof(int),cudaMemcpyDeviceToHost));
  std::cout << std::endl;
  for(int i=0; i<sz; i++)
   for(int j=0; j<sy; j++)
    for(int k=0; k<sx; k++)
     printf("[%d][%d][%d]=%d\n",i,j,k,res[i][j][k]);
 }

我已经将内核存储的数据修改为I-j+k,而不是I+j+k。此外,我还为下标创建了[z][y][x]顺序,因为这将建议使用线程索引计算安排,例如[threadIdx.z][threadIdx.y][threadIdx.x],这将最有利于合并访问。但是,内核中这种类型的多下标数组仍然会由于指针追踪来解析数据的最终位置而效率低下。

处理3D CUDA动态数组的方式应与处理3D C/C++动态数组的方式相同。唯一需要注意的是访问合并。请看一个例子,cudaMalloc3D的可能副本不是正确的使用方法。你链接的答案当然是一种方法。我给出的第二个示例,尽管看起来是针对2,2,2的硬编码,但实际上对于运行时确定的维度是可行的。如果您真的想要一个3d三重下标运行时确定的维度数组,那么这个问题与那个问题是重复的。