欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > block_size设置过大错误分析(查看CUDA设备线程块大小)

block_size设置过大错误分析(查看CUDA设备线程块大小)

2024/10/24 10:20:14 来源:https://blog.csdn.net/weixin_44222088/article/details/140641054  浏览:    关键词:block_size设置过大错误分析(查看CUDA设备线程块大小)

block_size设置过大错误分析(查看CUDA设备线程块大小)

  • 1 问题描述
  • 2 问题分析
  • 3 解决方法
  • 4 调试和验证
  • 5 查看设备线程块大小


1 问题描述

本人作为CUDA编程初学者,在学习编写使用CUDA计算矩阵相乘代码时发现,如果我的 block_size >= 64 时,代码就会计算出错,下面是我 block_size设置、定义网格和块尺寸以及调用核函数的方式。

在这里插入图片描述

  • d_ad_bd_c 是在GPU设备上分配的矩阵,分别表示输入矩阵A、B和结果矩阵C。

  • mns 是矩阵的尺寸参数,用于表示矩阵的行数和列数。

    • A矩阵是 m x n 矩阵
    • B矩阵是 n x s 矩阵

针对以上 block_size 设置过大导致CUDA计算结果出错的问题,我查了一些资料,得出以下的原因分析和解决方法。


2 问题分析

当 block_size >= 64 时,计算结果出错的原因可能是由于线程块(block)的尺寸超出了 GPU 的资源限制。具体问题可能来自以下几个方面:

1. 线程块大小超出限制
不同的 GPU 设备对于每个线程块中的线程数是有最大限制的。典型的 CUDA 设备限制是每个线程块最多包含 1024 个线程。如果我的 block_size = 64,根据我的核函数调用方式,则每个线程块包含 64 * 64 = 4096 个线程,远远超过了这个限制,这就是我的CUDA源代码产生错误的原因。那么根据这个原因,可以算出我的 block_size 最大可取 32,此时每个线程块包含的 32 *32 = 1024 个线程,达到本设备的最大线程数。

2. 共享内存和寄存器的限制
每个线程块中的线程数增大,会增加对共享内存和寄存器的需求,超出设备的限制可能会导致无法正常分配资源,进而影响计算的正确性。

3. 全局内存访问模式
当线程块变得非常大时,全局内存访问模式可能会变得不再是共启发性的,这会导致内存访问效率下降,从而影响计算结果的正确性。


3 解决方法

可以调整线程块的大小,使得每个线程块中的线程数不超过 GPU 设备的限制。以下是调整后的代码片段:

const int block_size = 16; // 或其他适合的值,小于等于 32

同时,确保在定义 CUDA 核函数的网格和块尺寸时使用适当的计算方式:

unsigned int grid_rows = (m + block_size - 1) / block_size;
unsigned int grid_cols = (s + block_size - 1) / block_size;
dim3 dimGrid(grid_cols, grid_rows);
dim3 dimBlock(block_size, block_size);

4 调试和验证

可以通过以下步骤来调试和验证:

打印出线程块和网格的尺寸,确保其在合理范围内。

尝试使用较小的 block_size,比如 16 或 32,并观察结果是否正确。

使用 CUDA 提供的设备查询函数 cudaDeviceProp 获取设备的属性,确保分配的资源在设备支持的范围内。


5 查看设备线程块大小

以下是设备查询的示例代码:

cudaDeviceProp prop;
cudaGetDeviceProperties(&prop, 0);
printf("Max threads per block: %d\n", prop.maxThreadsPerBlock);
printf("Max threads dim: (%d, %d, %d)\n", prop.maxThreadsDim[0], prop.maxThreadsDim[1], prop.maxThreadsDim[2]);
printf("Max grid size: (%d, %d, %d)\n", prop.maxGridSize[0], prop.maxGridSize[1], prop.maxGridSize[2]);

这段代码使用CUDA API来获取和打印GPU设备的属性。首先,cudaDeviceProp结构体用于存储设备的属性信息。cudaGetDeviceProperties函数被调用来填充prop结构体,其中0表示查询当前设备(通常是默认设备)。然后,代码通过printf函数输出设备的最大线程数、线程维度和网格大小。

具体来说,它打印出每个线程块的最大线程数(maxThreadsPerBlock),线程块在每个维度的最大尺寸(maxThreadsDim),以及每个网格的最大尺寸(maxGridSize)。

我的Jetson Nano查询结果示例如下:
在这里插入图片描述

根据这些信息,我们就可以了解设备的计算能力和限制,以便在编写CUDA程序时进行适当的调整。


如果想要在CUDA代码运行结束时直接输出错误原因,可参考:

Cuda编程模型中常见的错误检测方法

本人是一名学生,也是正在学习Jetson的过程中,如有错误请批评指正!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com