我想添加两个大矩阵NxN(N是两个的倍数)并使用Cuda C并行化程序。我能够使用大小为512x512的矩阵运行程序。但如果我超越它(例如:1024x1024),那么它就会失败。我相信问题可能是CUDA每个块最多可以启动512个线程(?)。所以我的问题是如何更改程序,以便我可以使用任何大小的矩阵。
cuda kernel
__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];
}
}
块和网格大小:
//BLOCK_DIM is 512, N works upto 512, but not beyond
dim3 dimBlock(BLOCK_DIM, BLOCK_DIM);
dim3 dimGrid((int)ceil(N/dimBlock.x),(int)ceil(N/dimBlock.y));
数组是:matrix1[N][N]
matrix2[N][N]
答案 0 :(得分:2)
如果您在使用CUDA代码时遇到问题,建议您使用cuda-memcheck
运行代码并添加proper cuda error checking。
此:
dim3 dimBlock(BLOCK_DIM, BLOCK_DIM);
对于BLOCK_DIM
大于22或32(取决于GPU和CUDA版本),在CUDA中是不合法的。 CUDA内核限制为每块512或1024个线程,这是各个线程块维度的产品。因此,在您的情况下,BLOCK_DIM
* BLOCK_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(N/dimBlock.x),(int)ceil(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
$