【发布时间】:2014-11-29 22:22:44
【问题描述】:
我编写了一小段代码,使用 CUDA 将 2 个方阵相乘。然而,事实证明大多数单元格计算错误。根据我用过的教程,一切都会好起来的。
__global__ void gpuMM(int *C, int *A, int *B, int N)
{
int row = blockIdx.x*blockDim.x + threadIdx.x;
int col = blockIdx.y*blockDim.y + threadIdx.y;
int sum = 0;
for (int n = 0; n < N; ++n)
sum += A[row*N+n]*B[n*N+col];
C[row*N+col] = sum;
}
#define ROW_SIZE 5
#define MATRIX_LENGTH ROW_SIZE*ROW_SIZE
#define BLOCK_SIZE 16
void MultiplyMatrixCUDA(int * pResult, int* pFactorA, int*pFactorB)
{
int size = MATRIX_LENGTH*sizeof(int);
int *dA,*dB,*dC;
cudaMalloc(&dA,size);
cudaMalloc(&dB,size);
cudaMalloc(&dC,size);
int K = 100;
dim3 threadBlock(BLOCK_SIZE,BLOCK_SIZE);
dim3 grid(K,K);
printf("A:\n");
DrawMatrix(pFactorA);
printf("\n");
printf("B:\n");
DrawMatrix(pFactorB);
printf("\n");
// Copy matrices from the host to device
cudaMemcpy(dA,pFactorA,size,cudaMemcpyHostToDevice);
cudaMemcpy(dB,pFactorB,size,cudaMemcpyHostToDevice);
//Execute the matrix multiplication kernel
gpuMM<<<grid,threadBlock>>>(dC,dA,dB,ROW_SIZE);
// Allocate memory to store the GPU answer on the host
int *C;
C = new int[MATRIX_LENGTH];
// Now copy the GPU result back to CPU
cudaMemcpy(C,dC,size,cudaMemcpyDeviceToHost);
cudaFree(dA);
cudaFree(dB);
cudaFree(dC);
printf("\nC from CUDA:\n");
DrawMatrix(C);
printf("\nC:\n");
DrawMatrix(MultiplyWithCPU(pResult,pFactorA, pFactorB)); // the code of multiplying function is irrevelant, I'm sure it works fine (double-checked)
}
结果表明矩阵乘以标准 CPU 方法是正确的,但 CUDA 是错误的:
第一行总是正确的,但所有其他部分都是完全随机的。有时它们是消极的,有时不是。有时它们接近真实值,有时它们完全不同。
我的错误是什么?我看不出哪里失败了。算法看起来不错,变量似乎传递正确,但有些东西不起作用。
--- 编辑
所有变量(pResult 和两个 pFactors)都在代码的其他部分初始化(然后删除)。
【问题讨论】:
-
pResult在哪里初始化? -
@PaulMcKenzie 它们在我调用
MultiplyMatrixCUDA之前在我的main()中进行了初始化。我已经编辑了我的问题。 -
您正在处理 5x5 矩阵,但您的块大小为 16x16。这意味着除了一个线程试图在非常真实的 (row,col) = (1,0) 上工作之外,还有一个线程试图在不存在的 (row,col) = (0,5) 上工作 -但是这两项重叠(0*N + 5 = 1*N + 0 = 5)。因此,您有多个工作项写入 C 的同一个元素,其中一些正在访问内存的无效部分,从而产生无意义的结果。在 gpuMM 中,您应该测试该行
-
@JonathanDursi 谢谢,我一到家里的电脑就检查一下。