我是CUDA的新手。我试图添加两个向量,它工作正常。现在我想添加两个矩阵。我想使用二维线程(threadIdx.x和threadIdx.y)添加两个矩阵。我在Internet上找到了这段代码,并且我做了一些更改来显示结果。它汇编。但显示意外的结果,它看起来像内存地址。请帮帮我,谢谢你。
#include <stdio.h>
#include <stdlib.h>
#define N 5
#define BLOCK_DIM 10
__global__ void matrixAdd (int *a, int *b, int *c) {
int col = blockIdx.x * blockDim.x + threadIdx.x;
int row = blockIdx.y * blockDim.y + threadIdx.y;
int index = col + row * N;
if (col < N && row < N) {
c[index] = a[index] + b[index];
}
}
int main() {
int a[N][N], b[N][N], c[N][N];
int *dev_a, *dev_b, *dev_c;
int size = N * N;
for(int i=0; i<N; i++)
for (int j=0; j<N; j++){
a[i][j] = 1;
b[i][j] = 2;
}
cudaMalloc((void**)&dev_a, size);
cudaMalloc((void**)&dev_b, size);
cudaMalloc((void**)&dev_c, size);
cudaMemcpy(dev_a, a, size, cudaMemcpyHostToDevice);
cudaMemcpy(dev_b, b, size, cudaMemcpyHostToDevice);
dim3 dimBlock(BLOCK_DIM, BLOCK_DIM);
dim3 dimGrid((int)ceil(N/dimBlock.x),(int)ceil(N/dimBlock.y));
matrixAdd<<<dimGrid,dimBlock>>>(dev_a,dev_b,dev_c);
cudaDeviceSynchronize();
for(int i=0; i<N; i++){
for (int j=0; j<N; j++){
printf("%d\t", c[i][j] );
}
printf("\n");
}
cudaMemcpy(c, dev_c, size, cudaMemcpyDeviceToHost);
cudaFree(dev_a);
cudaFree(dev_b);
cudaFree(dev_c);
}
,输出
0 0 -780197879 32659 1
0 452489360 32764 6303208 0
4198328 0 452489376 32764 4198181
0 2 0 4198557 0
4196864 0 0 0 4198480
我的预期输出是元素3的5x5矩阵。请帮助我。
答案 0 :(得分:2)
如果您遇到CUDA代码问题,应始终使用proper cuda error checking并使用cuda-memcheck
运行代码。我建议您在此处寻求帮助之前 。即使您不理解错误输出,它也会对那些试图帮助您的人有所帮助。
如果您已完成正确的CUDA错误检查,则会在内核启动时收到“无效参数”错误的通知。它是由于这个计算而产生的:
dim3 dimGrid((int)ceil(N/dimBlock.x),(int)ceil(N/dimBlock.y));
如果在计算后打印出实际计算值:
printf("dimGrid.x = %d, dimGrid.y = %d\n", dimGrid.x, dimGrid.y);
你会发现它们都是零。这是非法的。
这个结构:
N/dimBlock.x
正在使用整数除法。如果值N = 5且dimBlock.x = 10,则这两个数的整数除以零。 ceil
的使用不会影响您的写作方式。
有很多方法可以修复它。一种可能的方法是像这样进行算术:
dim3 dimGrid((N+dimBlock.x-1)/dimBlock.x, (N+dimBlock.y-1)/dimBlock.y);
下一个错误在于计算size
变量:
int size = N * N;
cudaMalloc
和cudaMemcpy
,如malloc
和memcpy
,预计字节的大小。所以你应该这样做:
int size = N * N * sizeof(int);
最后,您希望将数据复制回主机,然后再将其打印出来。所以这不正确:
for(int i=0; i<N; i++){
for (int j=0; j<N; j++){
printf("%d\t", c[i][j] );
}
printf("\n");
}
cudaMemcpy(c, dev_c, size, cudaMemcpyDeviceToHost);
你想这样做:
cudaMemcpy(c, dev_c, size, cudaMemcpyDeviceToHost);
for(int i=0; i<N; i++){
for (int j=0; j<N; j++){
printf("%d\t", c[i][j] );
}
printf("\n");
}
这是一个工作示例,显示了对代码的上述修改:
$ cat t1058.cu
#include <stdio.h>
#include <stdlib.h>
#define N 5
#define BLOCK_DIM 10
__global__ void matrixAdd (int *a, int *b, int *c) {
int col = blockIdx.x * blockDim.x + threadIdx.x;
int row = blockIdx.y * blockDim.y + threadIdx.y;
int index = col + row * N;
if (col < N && row < N) {
c[index] = a[index] + b[index];
}
}
int main() {
int a[N][N], b[N][N], c[N][N];
int *dev_a, *dev_b, *dev_c;
int size = N * N * sizeof(int);
for(int i=0; i<N; i++)
for (int j=0; j<N; j++){
a[i][j] = 1;
b[i][j] = 2;
}
cudaMalloc((void**)&dev_a, size);
cudaMalloc((void**)&dev_b, size);
cudaMalloc((void**)&dev_c, size);
cudaMemcpy(dev_a, a, size, cudaMemcpyHostToDevice);
cudaMemcpy(dev_b, b, size, cudaMemcpyHostToDevice);
dim3 dimBlock(BLOCK_DIM, BLOCK_DIM);
//dim3 dimGrid((int)ceil(N/dimBlock.x),(int)ceil(N/dimBlock.y));
dim3 dimGrid((N+dimBlock.x-1)/dimBlock.x, (N+dimBlock.y-1)/dimBlock.y);
printf("dimGrid.x = %d, dimGrid.y = %d\n", dimGrid.x, dimGrid.y);
matrixAdd<<<dimGrid,dimBlock>>>(dev_a,dev_b,dev_c);
cudaDeviceSynchronize();
cudaMemcpy(c, dev_c, size, cudaMemcpyDeviceToHost);
for(int i=0; i<N; i++){
for (int j=0; j<N; j++){
printf("%d\t", c[i][j] );
}
printf("\n");
}
cudaFree(dev_a);
cudaFree(dev_b);
cudaFree(dev_c);
}
$ nvcc -o t1058 t1058.cu
$ cuda-memcheck ./t1058
========= CUDA-MEMCHECK
dimGrid.x = 1, dimGrid.y = 1
3 3 3 3 3
3 3 3 3 3
3 3 3 3 3
3 3 3 3 3
3 3 3 3 3
========= ERROR SUMMARY: 0 errors
$