管理二维CUDA阵列

Managing a 2D CUDA Array

本文关键字:二维 CUDA 阵列 管理      更新时间:2023-10-16

我正试图将一个2d数组传递给内核,以便每个线程都可以访问index=threadIdx.x+(blockIdx.x*blockDim.x),但我很难弄清楚如何做到这一点以及如何将数据复制回来。

size_t pitch;
cudaMallocPitch(&d_array, &pitch, block_size * sizeof(int), num_blocks);
cudaMemset2D(d_array, pitch, 0, block_size * sizeof(int), num_blocks * sizeof(int));
kernel<<<grid_size, block_size>>>(d_array, pitch);
cudaMemcpy2D(h_array, pitch, d_array, pitch, block_size, num_blocks, cudaMemcpyDeviceToHost);
for (num_blocks)
  for(block_size)
    h_array[block][thread] should be 1
__global__ void kernel(int *array, int pitch) {
  int *row = (int*)((char*)array + blockIdx.x * pitch);
  row[threadIdx.x] = 1;
  return;
}

我做错了什么?

您的cudaMemset2D正在访问您之前使用cudaMallocPitch分配的更大内存空间。此外,您的cuda Memcpy2D正在复制该内存的一小部分。

您应该以以下方式使用该功能:

cudaMallocPitch(&d_array, &pitch, block_size * sizeof(int), num_blocks);
cudaMemset2D(d_array, pitch, 0, block_size * sizeof(int), num_blocks) // * sizeof(int)); <- This size is bigger than the previously declared
kernel<<<grid_size, block_size>>>(d_array, pitch);
cudaMemcpy2D(h_array, pitch, d_array, pitch, block_size * sizeof(int) /* you forgot this here */, num_blocks, cudaMemcpyDeviceToHost);

这是一个完整的代码,它通过了基本测试,并修复了@hidrargyro提到的错误:

$ cat t236.cu
#include <stdio.h>
#define cudaCheckErrors(msg) 
    do { 
        cudaError_t __err = cudaGetLastError(); 
        if (__err != cudaSuccess) { 
            fprintf(stderr, "Fatal error: %s (%s at %s:%d)n", 
                msg, cudaGetErrorString(__err), 
                __FILE__, __LINE__); 
            fprintf(stderr, "*** FAILED - ABORTINGn"); 
            exit(1); 
        } 
    } while (0)

__global__ void kernel(int *array, int pitch) {
  int *row = (int*)((char*)array + blockIdx.x * pitch);
  row[threadIdx.x] = 1;
  return;
}
int main(){
int *d_array, *h_array;
int block_size = 256;
int num_blocks = 256;
int grid_size = num_blocks;
h_array=(int *)malloc(block_size*num_blocks*sizeof(int));
if (h_array==0) {printf("malloc failn"); return 1;}
cudaMalloc((void **)&d_array, block_size*num_blocks*sizeof(int));
cudaCheckErrors("cudaMalloc fail");
size_t pitch;
cudaMallocPitch(&d_array, &pitch, block_size * sizeof(int), num_blocks);
cudaCheckErrors("cudaMallocPitch fail");
cudaMemset2D(d_array, pitch, 0, block_size * sizeof(int), num_blocks);
cudaCheckErrors("cudaMemset2D fail");
kernel<<<grid_size, block_size>>>(d_array, pitch);
cudaDeviceSynchronize();
cudaCheckErrors("kernel fail");
cudaMemcpy2D(h_array, block_size*sizeof(int), d_array, pitch, block_size*sizeof(int), num_blocks, cudaMemcpyDeviceToHost);
cudaCheckErrors("cudaMemcpy 2D fail");
for (int i = 0; i<num_blocks; i++)
  for(int j = 0; j<block_size; j++)
    if (h_array[i*block_size+j] != 1) {printf("mismatch at i=%d, j=%d, should be 1, was %dn", i,j,h_array[i*block_size+j]); return 1;}
printf("successn");
return 0;
}
$ nvcc -arch=sm_20 -o t236 t236.cu
$ ./t236
success
$