【发布时间】:2013-12-11 01:30:32
【问题描述】:
我正在尝试使用 Cuda 编程。作为其中的一部分,我正在尝试开发一种在 GPU 上运行的矩阵乘法算法。该算法适用于方阵,但不适用于 非方阵 矩阵。 这是我的内核
float* multiply_gpu(float* matrix1 , float* matrix2);
__global__ void mult(int rowsA , int columnsA, int rowsB,int columnsB, float *a,
float *b, float *result) {
int index = blockIdx.x * blockDim.x + threadIdx.x;
int result_size = rowsA*columnsB;
int value = 0;//the final result
//indices of values from input matrices
if (index < result_size) {
int index1 = (index/rowsA)*rowsA; //get nearest row
int index2 = index%columnsB; //get start column
int k = 0;
while (k<columnsA) { //columnsA == rowsB
value += a[index1]*b[index2]; //v = sum a_ik * b_kj
index1 ++;
index2 += columnsB;
k++;
}
result[index] = value;
}
}
在与我的主管进行了简短的健全性检查后,他没有发现任何问题。 我相信问题出在这个函数上:
float* multiply_gpu(float* matrix1 , float* matrix2) {
//the dimensions of the matrices
size_t available, total;
cudaError_t error;
cudaError err = cudaMemGetInfo(&available, &total);
if(err != cudaSuccess){
printf("There was an error: %s\n", cudaGetErrorString(err));
}
int height1 = matrix1[0];
int width1 = matrix1[1];
int height2 = matrix2[0];
int width2 = matrix2[1];
if (width1!=height2) {
return NULL;
}
//this array contains the result of the operation
float* result = (float *) malloc(height1*width2*sizeof(float));
//pointers for device matrices
float *d_matrix1;
float *d_matrix2;
float *d_result;
//allocate memory for matrices
error = cudaMalloc((void **)&d_matrix1,(size_t)height1*width1*sizeof(float));
if (error != cudaSuccess) {
fprintf(stderr, "Failed to allocate memory (error code %s)!\n", cudaGetErrorString(error));
exit(EXIT_FAILURE);
}
error = cudaMalloc((void **)&d_matrix2,height2*width2*sizeof(float));
if (error != cudaSuccess) {
fprintf(stderr, "Failed to allocate memory (error code %s)!\n", cudaGetErrorString(error));
exit(EXIT_FAILURE);
}
error = cudaMalloc((void **)&d_result,height1*width2*sizeof(float));
if (error != cudaSuccess) {
fprintf(stderr, "Failed to allocate memory (error code %s)!\n", cudaGetErrorString(error));
exit(EXIT_FAILURE);
}
//now copy matrices onto device -- note the offset of 2
error = cudaMemcpy(d_matrix1 , matrix1+2 , height1*width1*sizeof(float), cudaMemcpyHostToDevice);
if (error != cudaSuccess) {
fprintf(stderr, "Failed to copy memory (error code %s)!\n", cudaGetErrorString(error));
exit(EXIT_FAILURE);
}
error = cudaMemcpy(d_matrix2 , matrix2+2 , height2*width2*sizeof(float), cudaMemcpyHostToDevice);
if (error != cudaSuccess) {
fprintf(stderr, "Failed to copy memory (error code %s)!\n", cudaGetErrorString(error));
exit(EXIT_FAILURE);
}
//launch multiplication kernel
//note I have tried adjusting the kernel values between <<< , >>> to no avail
mult<<<height1,width2>>>(height1,width1,height2,width2,d_matrix1,d_matrix2,d_result);
printf("%d %d %d %d\n",height1,width1,height2,width2);
//make the host block until mult is finished running
//printf("finished multiplying\n");
cudaDeviceSynchronize();
//copy result back
error = cudaMemcpy(result,d_result,height1*width2*sizeof(float),cudaMemcpyDeviceToHost);
if (error != cudaSuccess) {
fprintf(stderr, "Failed to copy memory (error code %s)!\n", cudaGetErrorString(error));
exit(EXIT_FAILURE);
}
//free now unneeded cuda memory
cudaFree(d_matrix1);
cudaFree(d_matrix2);
cudaFree(d_result);
printf("GOT RESULT\n");
for (int i=0;i<height1*width2;i++) {
printf("%f ",result[i]);
}
printf("\n");
//result ready to be returned
return result;
}
请注意,作为 multiply_gpu 参数的矩阵的高度在索引 0 处,宽度在索引 1 处。结果矩阵没有此信息。
一个错误计算的例子: 当我将以下数组输入 multiply_gpu - {2,3,1,2,3,4,5,6} , {3,2,1,2,3,4 ,5,6} 答案应该是 {22,28,49,64} 但我的单元测试会生成 {22,28,40,52}。很近!请注意,对于 (1,2,3)*(1,2,3) (不是正方形)的点积,算法很满意......这里的错误可能是什么?感谢您的任何帮助。如果我独立找到解决方案,将发布解决方案。
【问题讨论】:
-
关于矩阵乘法的CUDA标签有不少问题。你有没有看过?如果您使用
cuda-memcheck运行代码会发生什么? SO 期望:“有关您编写的代码问题的问题必须在问题本身中描述具体问题 - 并包括有效的代码来重现它。请参阅 SSCCE.org 以获得指导。” 投票结束。您尚未提供 SSCCE.org 代码。 -
是的,矩阵乘法在 GPU 上很常见,并且有很多关于它的问题。我已经阅读了它们,但可能还不够彻底。我只是不知所措,来到这里进行理智检查。感谢您提供指向 SSCCE.org 的链接——我现在正在查看它。我也在学习 cuda-memcheck。总的来说,我面临的这个错误正在消耗我。我认为需要更多地关注我自己的代码,并且需要回顾一下其他矩阵乘法器。
-
我更新了我的答案,因为我的答案仍然不太正确。我认为现在是正确的 - 它适用于您提到的案例以及我尝试过的其他三个案例。
标签: matrix cuda gpu multiplication