【问题标题】:CUDA C Matrix MultiplicationCUDA C矩阵乘法
【发布时间】:2012-12-09 23:49:31
【问题描述】:

已编辑以与链接问题后的当前状态相对应。

我目前正在尝试在 CUDA 中重新实现基本的矩阵乘法,虽然我的代码适用于方阵和尺寸为 8 的倍数的矩形矩阵,但它似乎不适用于尺寸不是倍数的矩形矩阵8 个。

以下是我的内核乘法函数:

 __global__ void matrixMultiply(float * A, float * B, float * C,
               int numARows, int numAColumns,
               int numBRows, int numBColumns,
               int numCRows, int numCColumns) {
    int Row = blockIdx.y * blockDim.y + threadIdx.y;
    int Col = blockIdx.x * blockDim.x + threadIdx.x;
    if (numAColumns != numBRows) return ;
    if ((Row < numARows) && (Col < numBColumns)){
        float Cvalue = 0;
        for (int k = 0 ; k < numAColumns ; ++k )
            Cvalue += A[Row*numAColumns + k] * B[k * numBColumns + Col];
        C[Row*numCColumns + Col] = Cvalue;
    }

}

以下是内存分配(为了可读性我删掉了错误检查):

cudaMalloc((void**) &deviceA, ARows*sizeof(float)*AColumns);
cudaMalloc((void**) &deviceB, BRows*sizeof(float)*BColumns);
cudaMalloc((void**) &deviceC, CRows*sizeof(float)*CColumns);
cudaMemcpy(deviceA, hostA, ARows*sizeof(float)*AColumns, cudaMemcpyHostToDevice);
cudaMemcpy(deviceB, hostB, BRows*sizeof(float)*BColumns, cudaMemcpyHostToDevice);
cudaMemcpy(deviceC, hostC, CRows*sizeof(float)*CColumns, cudaMemcpyHostToDevice);

虽然下面是调用:

dim3 dimGrid((int)ceil(numCRows / 8.0) , (int)ceil(numCColumns / 8.0), 1);
dim3 dimBlock(8 , 8, 1);
multiplyMatrices<<<dimGrid,dimBlock>>>(deviceA, deviceB, deviceC, numARows, AColumns, BRows, BColumns, CRows, CColumns);

最后将内存移回: cudaMemcpy(hostC, deviceC, CRows*sizeof(float)*CColumns, cudaMemcpyDeviceToHost);

现在我已经反复跟踪我的算法,我认为它没有任何问题,所以我个人认为我使用的块/网格大小调整方案可能有问题。如果有比我更了解 CUDA/C 的人(这里是 Ruby/JavaScript 的人),可以看看它,并引导我了解我到底做错了什么,我将非常感激。

【问题讨论】:

  • This question 可能感兴趣。
  • 为什么我们需要所有的行和列变量? numARows、ARows、CRows 不是都必须是同一个数字吗?对于 BColumns 和 CColums 也是如此。无论如何,因为事情适用于可被 8 整除的尺寸,我的猜测是,当尺寸不能被 8 整除(在边界上强制额外的块)时,你的一些线程没有正确关闭。所以我会关注这条线:if ((Row &lt; numARows) &amp;&amp; (Col &lt; numBColumns)){ 如果你把它改成:if ((Row &lt; numCRows) &amp;&amp; (Col &lt; numCColumns)){ 会发生什么?或者,我想查看每个行和列变量的数值。
  • 所有这些输入参数都是教师给出的模板代码的一部分。
  • 您没有将矩阵 B 复制到设备中?还是问题中的错字?
  • 好地方,不幸的是它只是一个错字。修改问题

标签: c matrix cuda parallel-processing gpu


【解决方案1】:

问题在于您正在创建的网格大小:

dim3 dimGrid((int)ceil(numCRows / 8.0) , (int)ceil(numCColumns / 8.0), 1);

由于行是矩阵的 Y 维度,列是 X 维度,因此您实际上是在创建转置网格。

要创建正确的网格,请执行以下操作:

dim3 dimGrid((int)ceil(numCColumns / 8.0) , (int)ceil(numCRows / 8.0), 1);

更好的方法是执行以下操作:

dim3 dimGrid;

dimGrid.x = (numCColumns + dimBlock.x - 1)/dimBlock.x;

dimGrid.y = (numCRows + dimBlock.y - 1)/dimBlock.y;

【讨论】:

  • 谢谢!我的一个问题是,您是否有理由在事后设置 x 和 y 值而不是与网格一起初始化它们?此外,这种方法是否比天花板/投射更有效,还是有其他理由这样做?
  • 没有。没有理由。它只是为了代码的可读性。再次不,它只是保存了一个函数调用。
猜你喜欢
  • 2011-09-07
  • 2012-05-06
  • 1970-01-01
  • 2012-02-07
  • 2011-04-21
  • 2012-12-13
  • 1970-01-01
  • 2016-05-22
  • 2021-08-04
相关资源
最近更新 更多