【问题标题】:CUDA Vision Studio Trouble with KernelCUDA Vision Studio 内核问题
【发布时间】:2025-11-21 07:10:02
【问题描述】:

我有一个项目,我必须在 Visual Studio/CUDA 中使用 GPU 线程和块创建一个程序,其中包含 2 个随机数组 AB,用于在存储结果之前进行计算在第三个数组C 中,基于此等式的值:

C(1,j)=max(A(:,j)+max(B(:,j)) (注意:“:”运算符表示所有行)

这是我的内核函数

           __global__ void mykernel(int **a, int **b,int **c,const int width)
             {
int col= threadIdx.x;
int tempa=0;
int tempb=0;

for(int k=0;k<width;k++){

    int maxA=a[k][col];

    if  (maxA>tempa){
    tempa=maxA;
    }

    int maxB=b[k][col];

    if  (maxB>tempb){
    tempb=maxB;
    }

    }


c[0][col] =tempa+tempb;
}

还有我的主要

      int main()
       {
const int  dim= 5;
const int rows=5;
const int columns=5;
size_t dsize = rows*columns*sizeof(int);
//Αντίγραφα πινάκων δεδομένων της CPU
int *A[dim][dim];
int *B[dim][dim];
int *C[1][dim];

//Αντίγραφα πινάκων δεδομένων της GPU
int *d_A[dim][dim],*d_B[dim][dim],*d_C[1][dim]; 

//Εξασφάλιση μνήμης για τα αντίγραφα δεδομένων της CPU 
A[dim][dim]= (int *)malloc(dsize); 
B[dim][dim] = (int *)malloc(dsize); 
C[1][dim]= (int *)malloc(dsize);

//Γέμισμα των πινάκων με τυχαίες τιμές μεταξυ 
 for (int i=0;i<rows;i++)
   for (int j=0;j<columns;j++){


  *A[i][j]=rand() %5+1;
  *B[i][j]=rand() %5+1;

 }

//Εξασφάλιση μνήμης για τα αντίγραφα δεδομένων της GPU και αντιγραφή δεδομένων CPU προς GPU  
cudaMalloc((void **)&d_A, dsize);
cudaMemcpy(d_A, A, dsize, cudaMemcpyHostToDevice);

cudaMalloc((void **)&d_B, dsize);
cudaMemcpy(d_B, B, dsize, cudaMemcpyHostToDevice);

cudaMalloc((void **)&d_C, dsize);

//Κλήση Kernel συνάρτησης στην GPU με χρήση 5 Threads σε 1 Block

mykernel<<<1,5>>>(d_A,d_B,d_C,dim);

//Αντιγραφή αποτελέσματος στην μνήμη της CPU
cudaMemcpy(C, d_C, dsize, cudaMemcpyDeviceToHost);

//Εκκαθάριση Μνήμης για CPU και GPU
free(A);
free(B);
free(C);

cudaFree(d_A); cudaFree(d_B); cudaFree(d_C);

while(1){};
return 0;
  }

我认为我的算法是正确的,但在这一行中我收到以下错误:

线

mykernel<<<1,5>>>(d_A,d_B,d_C,dim);

错误

argument of type "int *(*)[5]" is incompatible with parameter of type "int **"

对我应该做什么有什么建议吗?

【问题讨论】:

  • P.S:这是我的第一篇文章,如果我弄乱了所需的格式,请提前道歉。 --> 第一篇文章的格式很好! ;-)
  • @Allan 谢谢我的朋友!真的很期待一个提示,因为我已经连续 4 个小时脑洞大开!哈哈
  • 这里明显缺乏对某些 C 编程概念的理解。这段代码中可能存在大约 3-6 种不同类型的错误,这些错误必须被解开才能实现某些功能。一般来说,您似乎对在 CUDA 中使用 2D 数组感兴趣,因此查看 this 可能会有所帮助,但它并不能直接解决您代码中的所有错误。

标签: c++ c cuda


【解决方案1】:
  1. 首先,每当您遇到 CUDA 代码问题时,我建议您使用 proper CUDA error checking 并使用 cuda-memcheck 运行您的代码(例如从命令行)。

  2. 这不是你想的那样:

    int *A[dim][dim];
    

    这是创建一个二维指针数组。你想要的是一个指向二维数组(int)的指针。

  3. 在 C 中,当你定义一个数组时,你不能给数组维度的元素赋值:

    A[dim][dim]= (int *)malloc(dsize); 
    

    数组的大小只能达到dim- 1。A[dim][dim] 不存在并且超出了数组定义的范围。这似乎与您对在 C 或 C++ 中使用 2D 数组的普遍困惑有关。

  4. 这一行同样被破坏(将数值分配给与未分配指针关联的区域),这进一步证明了您对 C 中的二维数组感到困惑:

    *A[i][j]=rand() %5+1;
    
  5. 您对d_Ad_Bd_C 的处理同样被破坏。

很明显,您希望在 CUDA 内核中使用 2D 数组,因此正确的方法可能是从一组 canonical examples 中选择一个方法。由于您似乎在编译时知道数组维度,我们将leverage that。这是一个展示模组的完整示例:

$ cat t1344.cu
#include <iostream>
const int dim = 5;
typedef int my_arr[dim];

__global__ void mykernel(my_arr *a, my_arr *b, my_arr *c,const int width)
{
int col= threadIdx.x;
int tempa=0;
int tempb=0;

for(int k=0;k<width;k++){

    int maxA=a[k][col];

    if  (maxA>tempa){
    tempa=maxA;
    }

    int maxB=b[k][col];

    if  (maxB>tempb){
    tempb=maxB;
    }

    }


c[0][col] =tempa+tempb;
}

int main()
       {
const int rows=dim;
const int columns=dim;
size_t dsize = rows*columns*sizeof(int);
//Αντίγραφα πινάκων δεδομένων της CPU;
my_arr *A, *B, *C;

//Αντίγραφα πινάκων δεδομένων της GPU
my_arr *d_A,*d_B,*d_C;

//Εξασφάλιση μνήμης για τα αντίγραφα δεδομένων της CPU
A = (my_arr *)malloc(dsize);
B = (my_arr *)malloc(dsize);
C = (my_arr *)malloc(dsize);

//Γέμισμα των πινάκων με τυχαίες τιμές μεταξυ
 for (int i=0;i<rows;i++)
   for (int j=0;j<columns;j++){


  A[i][j]=rand() %5+1;
  B[i][j]=rand() %5+1;

 }

//Εξασφάλιση μνήμης για τα αντίγραφα δεδομένων της GPU και αντιγραφή δεδομένων CPU προς GPU
cudaMalloc((void **)&d_A, dsize);
cudaMemcpy(d_A, A, dsize, cudaMemcpyHostToDevice);

cudaMalloc((void **)&d_B, dsize);
cudaMemcpy(d_B, B, dsize, cudaMemcpyHostToDevice);

cudaMalloc((void **)&d_C, dsize);

//Κλήση Kernel συνάρτησης στην GPU με χρήση 5 Threads σε 1 Block

mykernel<<<1,5>>>(d_A,d_B,d_C,dim);

//Αντιγραφή αποτελέσματος στην μνήμη της CPU
cudaMemcpy(C, d_C, dsize, cudaMemcpyDeviceToHost);
for (int i = 0; i < dim; i++)  std::cout << C[0][i] << std::endl;
//Εκκαθάριση Μνήμης για CPU και GPU
free(A);
free(B);
free(C);

cudaFree(d_A); cudaFree(d_B); cudaFree(d_C);

return 0;
  }
$ nvcc -arch=sm_35 -o t1344 t1344.cu
$ cuda-memcheck ./t1344
========= CUDA-MEMCHECK
9
8
8
9
8
========= ERROR SUMMARY: 0 errors
$

我还没有完全验证结果,但对我来说它们似乎是合理的。

【讨论】:

  • 首先,我真的很感谢你花时间陈述我犯的所有这些错误和困惑。我开始看到我认为的图片。所以在你给出的答案中我不能真正理解在您将数组定义为 int[5] 数组后它们应该是 2D 的。或者您没有编辑它,我必须按照您所说的选择一种方法?还有另一个问题(我知道我很累),我使用 rand 函数在将它们传输到 GPU 之前给它们随机值的方法无效,为什么?(假设我找到了一种方法将所需的 2D 以某种方式处理为 1D)
  • 我创建了 int[5] 数组的数组。 int[5] 数组的数组实际上是一个二维数组。指向int[5] 项的指针也可以是指向多个int[5] 项的指针,就像指向单个int 的指针也可以是指向多个int 的指针一样,因此是一个数组。您对rand() 的使用没有任何问题。但是,当您使用尚未正确初始化的指针(*A[i][j])获取该数值并分配给一个位置时,这将不起作用。这是非法的,并且不能保证您可以取回您存储在那里的价值。