问题描述
我很难理解代码中的错误在哪里。
该项目的目的是将两个矩阵相乘并比较顺序和并行之间的时间。
当我打印矩阵时,我看到设备矩阵基本上是空的。
此外,我将矩阵视为大小为n * n的数组。
谢谢!
//This program computes the multiplication of two Matrices GPU using CUDA
#include <stdio.h>
#include <cassert>
__global__ void matrixMul(int * m,int * n,int * p,int size)
{
//Calculate Row and Column
int row=threadIdx.y*blockDim.y+threadIdx.y;
int column=threadIdx.x*blockDim.x+threadIdx.x;
int p_sum=0;
for (int i = 0; i < size; i++)
{
p_sum += m[row*size + i] * n[i*size +column];
}
p[row*size + column] = p_sum;
}
void matrixMul_seq(int * m,int size){
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
for(int k = 0; k < size; k++){
p[i*size +j] += m[i*size +k] +n[k*size +j];
}
}
}
}
//Initialize matricies
void init_matricies(int * mat,int n){
for(int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
{
mat[i*n+j]=rand()%1024;
}
}
}
int main(int argc,char **argv)
{
//Set our problem Size(Default = 2^10 == 1024)
int n = 1<<10;
printf("Square Matrix of size:%d\n",n);
//Size in Bytes
size_t bytes=n*n*sizeof(bytes);
//Host matricies
int *h_m;
int *h_p;
int *h_n;
int *h_p_seq;
//Host matricies
int *d_m;
int *d_p;
int *d_n;
//Memory allocation for Host Matricies
h_m=(int*)malloc(bytes);
h_n=(int*)malloc(bytes);
h_p=(int*)malloc(bytes);
h_p_seq=(int*)malloc(bytes);
init_matricies(h_m,n);
init_matricies(h_n,n);
//Allocate memory on device side
cudaMalloc(&d_n,bytes);
cudaMalloc(&d_m,bytes);
cudaMalloc(&d_p,bytes);
//Copy data to Device
cudaMemcpy(d_m,h_m,bytes,cudaMemcpyHostToDevice);
cudaMemcpy(d_n,h_n,cudaMemcpyHostToDevice);
int threads_per_block =16;
dim3 block_size(threads_per_block,threads_per_block);
dim3 grid_size( n / block_size.x,n / block_size.y);
printf("Grid size X:%d,Grid size y:%d\n",grid_size.x,grid_size.y);
printf("THE RESULT OF THE SIZES: 2^6 * 2^4 * 2^6 * 2^4 \n");
matrixMul <<<grid_size,block_size>>>(d_m,d_n,d_p,n);
matrixMul_seq(h_m,h_p_seq,n);
cudaMemcpy(h_p,cudaMemcpyDeviceToHost);
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
//printf("Grid size X:%d,h_p[ n * i + j],h_p_seq[ n * i + j]);
assert(h_p[ n * i + j]==h_p_seq[ n * i + j]);
}
}
free(h_m);
free(h_p);
free(h_n);
free(h_p_seq);
cudaFree(d_m);
cudaFree(d_n);
cudaFree(d_p);
return 0;
}
解决方法
您的代码中存在各种问题:
-
您正在错误地计算内核索引变量。这是不正确的:
int row=threadIdx.y*blockDim.y+threadIdx.y; int column=threadIdx.x*blockDim.x+threadIdx.x;
应该是:
int row=blockIdx.y*blockDim.y+threadIdx.y; int column=blockIdx.x*blockDim.x+threadIdx.x;
-
您的计算函数中的矩阵运算不匹配。内核:
p_sum += m[row*size + i] * n[i*size +column]; ^ multiplication
主机代码:
p[i*size +j] += m[i*size +k] +n[k*size +j]; ^ addition
我们还从上面观察到,宿主代码对输出变量(
+=
做求和,而内核在做赋值 em>到输出变量(=
):p[row*size + column] = p_sum;
这与下一个问题有关。
-
malloc
不初始化数据。由于此操作正在创建将由宿主代码使用的输出数组,并对其求和,因此我们必须将此分配初始化为零:h_p_seq=(int*)malloc(bytes); memset(h_p_seq,bytes); // must add this line to initialize to zero
-
以字节为单位的数组大小的计算太大。您已将数组定义为
int
类型。但是您的尺寸计算是这样的:size_t bytes=n*n*sizeof(bytes);
int
是4字节的数量,而size_t
之类的bytes
变量是8字节的数量。这不会引起实际问题,但是不必要。我建议将其更改为:size_t bytes=n*n*sizeof(int);
解决了以上问题,您的代码对我而言正确运行。