用CUDA-C实现大矩阵加法

用CUDA-C实现大矩阵加法,c,matrix,cuda,parallel-processing,C,Matrix,Cuda,Parallel Processing,我想添加两个大矩阵NxN(N是2的倍数)并使用Cuda C并行化程序。我能够使用大小为512x512的矩阵运行程序。但是,如果我超出这个范围(例如:1024x1024),那么它就会失败。我相信问题可能是CUDA可以在每个块上最多启动512个线程(?)。所以我的问题是如何修改程序,这样我就可以修改任意大小的矩阵 cuda内核 __global__ void parMatrixAdd_kernel(float *a, float *b, float *c, int N) { int col

我想添加两个大矩阵NxN(N是2的倍数)并使用Cuda C并行化程序。我能够使用大小为512x512的矩阵运行程序。但是,如果我超出这个范围(例如:1024x1024),那么它就会失败。我相信问题可能是CUDA可以在每个块上最多启动512个线程(?)。所以我的问题是如何修改程序,这样我就可以修改任意大小的矩阵

cuda内核

__global__ void parMatrixAdd_kernel(float *a, float *b, float *c, int N) {

   int col = threadIdx.x + blockIdx.x * blockDim.x;
   int row = threadIdx.y + blockIdx.y * blockDim.y;
   int index = col + row * N;
   if (col < N && row < N) {
       c[index] = a[index] + b[index];
   }
}
数组是:
matrix1[N][N]
matrix2[N][N]

  • 每当您在使用CUDA代码时遇到问题,建议您使用
    CUDA memcheck
    运行代码,并添加

  • 这:

     dim3 dimBlock(BLOCK_DIM, BLOCK_DIM);
    
  • 对于大于22或32(取决于GPU和CUDA版本)的
    BLOCK_DIM
    在CUDA中不合法。CUDA内核限制为每个块512或1024个线程,这是单个threadblock维度的乘积。因此,在您的情况下,
    BLOCK\u DIM
    *
    BLOCK\u DIM
    必须小于512或1024,具体取决于GPU和CUDA版本。在任何情况下,将
    BLOCK_DIM
    设置为512都无法工作

  • 如果要在堆栈上创建这样的变量:

     float matrix1[N][N];
    
  • N
    变得更大时,这将导致麻烦,因为您可能会遇到堆栈大小的限制。(这与CUDA无关)而是动态创建这些变量(下面的代码中给出了一个示例)

    下面的代码(围绕您展示的部分构建)似乎适合我,并实现了上述更改。为了简洁起见,我省略了适当的cuda错误检查,但如果您在使用cuda代码时遇到问题,我建议您使用它。作为替代,我使用
    cuda memcheck
    运行它:

    $ cat t1002.cu
    #include <stdio.h>
    #include <math.h>
    
    const size_t BLOCK_DIM = 16;
    const size_t MY_N =  2048;
    
    const float tval1 = 1.0f;
    const float tval2 = 2.0f;
    
    __global__ void parMatrixAdd_kernel(float *a, float *b, float *c, int N) {
    
       int col = threadIdx.x + blockIdx.x * blockDim.x;
       int row = threadIdx.y + blockIdx.y * blockDim.y;
       int index = col + row * N;
       if (col < N && row < N) {
           c[index] = a[index] + b[index];
       }
    }
    
    typedef float my_mat[MY_N];
    
    int main(){
    
      my_mat *A, *B, *C;
      const size_t N = MY_N;
      size_t dsize = N*N*sizeof(float);
      A = (my_mat *)malloc(dsize);
      B = (my_mat *)malloc(dsize);
      C = (my_mat *)malloc(dsize);
    
      for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++) {
          A[i][j] = tval1;
          B[i][j] = tval2;
          C[i][j] = 0.0f;}
    
      float *d_A, *d_B, *d_C;
      cudaMalloc(&d_A, dsize);
      cudaMalloc(&d_B, dsize);
      cudaMalloc(&d_C, dsize);
    
      cudaMemcpy(d_A, A, dsize, cudaMemcpyHostToDevice);
      cudaMemcpy(d_B, B, dsize, cudaMemcpyHostToDevice);
    
      dim3 dimBlock(BLOCK_DIM, BLOCK_DIM);
      dim3 dimGrid((int)ceil((double)N/dimBlock.x),(int)ceil((double)N/dimBlock.y));
    
      parMatrixAdd_kernel<<<dimGrid, dimBlock>>>(d_A, d_B, d_C, N);
      cudaMemcpy(C, d_C, dsize, cudaMemcpyDeviceToHost);
      for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
          if (C[i][j] != (tval1+tval2)) {printf("mismatch at %d,%d was: %f, should be %f\n", i, j, C[i][j], (tval1+tval2)); return 1;}
      printf("Success!\n");
      return 0;
    }
    $ nvcc -o t1002 t1002.cu
    $ cuda-memcheck ./t1002
    ========= CUDA-MEMCHECK
    Success!
    ========= ERROR SUMMARY: 0 errors
    $
    
    $cat t1002.cu
    #包括
    #包括
    const size\u t BLOCK\u DIM=16;
    const size\u t MY\u N=2048;
    常数浮点数tval1=1.0f;
    常数浮点数tval2=2.0f;
    __全局\uuuvoid parMatrixAdd\u内核(浮点*a、浮点*b、浮点*c、整数N){
    int col=threadIdx.x+blockIdx.x*blockDim.x;
    int row=threadIdx.y+blockIdx.y*blockDim.y;
    int index=列+行*N;
    如果(列
  • 每当您在使用CUDA代码时遇到问题,建议您使用
    CUDA memcheck
    运行代码,并添加

  • 这:

     dim3 dimBlock(BLOCK_DIM, BLOCK_DIM);
    
  • 对于大于22或32(取决于GPU和CUDA版本)的
    BLOCK_DIM
    在CUDA中不合法。CUDA内核限制为每个块512或1024个线程,这是单个threadblock维度的乘积。因此,在您的情况下,
    BLOCK\u DIM
    *
    BLOCK\u DIM
    必须小于512或1024,具体取决于GPU和CUDA版本。在任何情况下,将
    BLOCK_DIM
    设置为512都无法工作

  • 如果要在堆栈上创建这样的变量:

     float matrix1[N][N];
    
  • N
    变得更大时,这将导致麻烦,因为您可能会遇到堆栈大小的限制。(这与CUDA无关)而是动态创建这些变量(下面的代码中给出了一个示例)

    下面的代码(围绕您展示的部分构建)似乎适合我,并实现了上述更改。为了简洁起见,我省略了适当的cuda错误检查,但如果您在使用cuda代码时遇到问题,我建议您使用它。作为替代,我使用
    cuda memcheck
    运行它:

    $ cat t1002.cu
    #include <stdio.h>
    #include <math.h>
    
    const size_t BLOCK_DIM = 16;
    const size_t MY_N =  2048;
    
    const float tval1 = 1.0f;
    const float tval2 = 2.0f;
    
    __global__ void parMatrixAdd_kernel(float *a, float *b, float *c, int N) {
    
       int col = threadIdx.x + blockIdx.x * blockDim.x;
       int row = threadIdx.y + blockIdx.y * blockDim.y;
       int index = col + row * N;
       if (col < N && row < N) {
           c[index] = a[index] + b[index];
       }
    }
    
    typedef float my_mat[MY_N];
    
    int main(){
    
      my_mat *A, *B, *C;
      const size_t N = MY_N;
      size_t dsize = N*N*sizeof(float);
      A = (my_mat *)malloc(dsize);
      B = (my_mat *)malloc(dsize);
      C = (my_mat *)malloc(dsize);
    
      for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++) {
          A[i][j] = tval1;
          B[i][j] = tval2;
          C[i][j] = 0.0f;}
    
      float *d_A, *d_B, *d_C;
      cudaMalloc(&d_A, dsize);
      cudaMalloc(&d_B, dsize);
      cudaMalloc(&d_C, dsize);
    
      cudaMemcpy(d_A, A, dsize, cudaMemcpyHostToDevice);
      cudaMemcpy(d_B, B, dsize, cudaMemcpyHostToDevice);
    
      dim3 dimBlock(BLOCK_DIM, BLOCK_DIM);
      dim3 dimGrid((int)ceil((double)N/dimBlock.x),(int)ceil((double)N/dimBlock.y));
    
      parMatrixAdd_kernel<<<dimGrid, dimBlock>>>(d_A, d_B, d_C, N);
      cudaMemcpy(C, d_C, dsize, cudaMemcpyDeviceToHost);
      for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
          if (C[i][j] != (tval1+tval2)) {printf("mismatch at %d,%d was: %f, should be %f\n", i, j, C[i][j], (tval1+tval2)); return 1;}
      printf("Success!\n");
      return 0;
    }
    $ nvcc -o t1002 t1002.cu
    $ cuda-memcheck ./t1002
    ========= CUDA-MEMCHECK
    Success!
    ========= ERROR SUMMARY: 0 errors
    $
    
    $cat t1002.cu
    #包括
    #包括
    const size\u t BLOCK\u DIM=16;
    const size\u t MY\u N=2048;
    常数浮点数tval1=1.0f;
    常数浮点数tval2=2.0f;
    __全局\uuuvoid parMatrixAdd\u内核(浮点*a、浮点*b、浮点*c、整数N){
    int col=threadIdx.x+blockIdx.x*blockDim.x;
    int row=threadIdx.y+blockIdx.y*blockDim.y;
    int index=列+行*N;
    如果(列