C++ CUDA:为啥我的块尺寸不起作用?

Posted

技术标签:

【中文标题】C++ CUDA:为啥我的块尺寸不起作用?【英文标题】:C++ CUDA: Why aren't my block dimensions working?C++ CUDA:为什么我的块尺寸不起作用? 【发布时间】:2022-01-16 11:09:59 【问题描述】:

我正在使用书中的一个示例来解决 4x4 矩阵乘法。然而,这本书只提供了内核代码,所以剩下的程序就交给我了。这本书说使用 2 的块宽度,但是我不能让它与 dim3 变量一起使用。这是内核:

__global__ void matmul_basic(float *c, float *a, float *b, unsigned int width)
   
    printf("Width: %d\n", width);
    printf("BlockDim.x: %d, BlockDim.y: %d, BlockDim.z: %d\n", blockDim.x, blockDim.y, blockDim.z);
    printf("GridkDim.x: %d, GridDim.y: %d, GridDim.z: %d\n", gridDim.x, gridDim.y, gridDim.z);
    printf("Blockidx.x: %d, Blockidx.y: %d, Blockidx.z: %d\n", blockIdx.x, blockIdx.y, blockIdx.z);
    printf("threadIdx.x %d, threadIdx.y: %d, threadIdx.z: %d\n", threadIdx.x, threadIdx.y, threadIdx.z);
    // Calculate the row index of the c element and a
    int Row = blockIdx.y * blockDim.y + threadIdx.y;
    // Calculate the column index of c and b
    int Col = blockIdx.x * blockDim.x + threadIdx.x;
    // Sense check
    printf("Row: %d\tCol: %d\n", Row, Col);

    if ((Row < width) && (Col < width)) 
        float Pvalue = 0;
        // each thread computes one element of the block sub-matrix
        for (size_t k = 0; k < width; k++)
        
            Pvalue += a[Row * width + k] * b[k * width + Col];
        
        c[Row * width + Col] = Pvalue;
    
    else 
        printf("Dimensions out of bounds. Row: %d, Col: %d\n", Row, Col);
    

我知道打印语句过多,但我只是想验证尺寸。以下是函数调用中的维度:

dim3 dimGrid = (1, 1, 1);
dim3 dimBlock = (2, 2, 1);
matmul_basic <<<dimGrid, dimBlock>>> (d_c, d_a, d_b, width);

这应该是一个 2x2 维度的线程块? 最后,这是读数:

Width: 4
BlockDim.x: 1, BlockDim.y: 1, BlockDim.z: 1
GridkDim.x: 1, GridDim.y: 1, GridDim.z: 1
Blockidx.x: 0, Blockidx.y: 0, Blockidx.z: 0
threadIdx.x 0, threadIdx.y: 0, threadIdx.z: 0
Row: 0  Col: 0
Kernel Complete, transferring results...
20218 -1.07374e+08 -1.07374e+08 -1.07374e+08
-1.07374e+08 -1.07374e+08 -1.07374e+08 -1.07374e+08
-1.07374e+08 -1.07374e+08 -1.07374e+08 -1.07374e+08
-1.07374e+08 -1.07374e+08 -1.07374e+08 -1.07374e+08

所以它永远不会超过第一个线程,它认为块大小是 1x1x1?它也永远不会进入表明它在矩阵维度之外的 else 语句。

我确定我在做一些愚蠢的事情,或者我误解了维度的工作原理。任何帮助将不胜感激。谢谢!

编辑: 从 printf 语句中添加宽度初始化和读出:

初始化:

// Determine matrix dimensions
const int width = 4;

上面原始部分中的读数已被编辑为包括宽度。

【问题讨论】:

“读数”似乎缺少第一行(printf("Width: %d\n", width); 的输出)。这可能很重要,因为在您的帖子中没有其他地方,您是否向我们展示了您为 width 变量赋值的位置。 @AdrianMole 你是对的,对不起。我现在已将其添加到编辑中。 【参考方案1】:

它认为块大小是 1x1x1?

是的。

为什么我的块尺寸不起作用?

因为:

dim3 dimBlock = (2, 2, 1);

没有做你认为它正在做的事情,而且它不是初始化dim3 变量的正确方法。您可能想花点时间思考一下 C++ 中的表达式 (2,2,1) 求值 是什么。在引擎盖下,dim3 变量是具有 3 个组件的struct。您不能在 C++ 中以这种方式设置 3 元素结构的所有 3 个组件。

无论如何,你会遇到这样的事情会更好,它会调用构造函数来设置值:

dim3 dimBlock(2, 2, 1);

或者这个,哪个没有:

dim3 dimBlock; 
dimBlock.x = 2;
dimBlock.y = 2;
dimBlock.z = 1;

我还要指出,对于 4x4 问题,您的网格大小也不正确,但您可能会弄清楚。

【讨论】:

非常感谢,这是我的一个愚蠢的误读。对此还是很陌生!你对网格大小是正确的,还没有解决这个问题。你让我头疼了,再次感谢!

以上是关于C++ CUDA:为啥我的块尺寸不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用命名空间在我的 C++ 项目中不起作用?

为啥 cvWaitKey(0) 不起作用?

为啥模板参数推导在 C++ 中不起作用?

为啥我的图像马赛克中的自定义维度在 geoserver getmap 请求中不起作用?

为啥我的 weighted_grade 变量不起作用?

为啥 C++ CLI 索引属性在 C# 中不起作用?