CUDA Matrix Multiplication and Transpose

💡 原文中文,约9100字,阅读约需22分钟。
📝

内容提要

本文通过代码实践讲解CUDA矩阵乘法与转置。GPU包含寄存器、共享内存、全局内存等存储单元。矩阵乘法中,每个线程计算输出矩阵的一个元素,读取M的一行和N的一列进行乘积累加,二维坐标按y*width+x映射为一维索引。矩阵转置则交换行列索引。文中提供完整CUDA代码,并与CPU结果对比验证,还介绍了使用nvprof查看性能及RGB转灰度图练习。

🔎

延伸解读

线程索引与内存映射

在CUDA中,线程的二维坐标通过blockIdx和threadIdx计算,并映射为一维全局索引。矩阵元素按行优先存储,因此坐标(x,y)对应索引y*width+x。这种映射方式使得每个线程能准确访问矩阵中的特定元素,是并行处理矩阵操作的基础。

矩阵乘法的并行策略

矩阵乘法中,每个线程负责计算结果矩阵的一个元素。线程读取左矩阵的一行和右矩阵的一列,执行乘积累加。通过将线程映射到输出矩阵的每个位置,GPU可以同时计算多个元素,显著提升计算效率。

矩阵转置的实现要点

矩阵转置通过交换行列索引实现。每个线程读取输入矩阵的(x,y)位置,并写入输出矩阵的(y,x)位置。由于转置操作改变了内存访问模式,可能影响性能,但通过合理的线程组织仍能有效并行化。

性能分析与验证

使用nvprof工具可以查看CUDA程序的性能指标,帮助优化。文中通过对比CPU和GPU的计算结果来验证正确性,确保并行计算的准确性。此外,还提供了RGB转灰度图的练习,展示CUDA在图像处理中的应用。

❓

Q&A

CUDA中GPU有哪些存储单元?

GPU包含多种存储单元:每个线程可读写的寄存器(registers)和本地内存(local memory),每个线程块可读写的共享内存(shared memory),每个网格可读写的全局内存(global memory),以及只读的常量内存(constant memory)和纹理内存(texture memory)。主机(host)与全局内存、常量内存和纹理内存进行交互。

CUDA矩阵乘法中每个线程如何计算输出矩阵的一个元素?

每个线程计算输出矩阵P的一个元素:线程读取矩阵M的一行和矩阵N的一列,对每对元素执行乘法和加法,累加得到结果。线程的二维坐标通过blockIdx和threadIdx计算,然后映射到一维索引进行内存访问。

在CUDA中如何将二维矩阵坐标映射到一维索引?

二维矩阵在内存中按一维连续地址存储。对于宽为width、高为height的矩阵,坐标(x,y)对应的一维索引为:y * width + x。在CUDA核函数中,通常用row表示行(y方向),col表示列(x方向),索引计算为row * width + col。

CUDA矩阵转置的核函数如何实现?

矩阵转置核函数中,每个线程计算输出矩阵的一个元素:读取输入矩阵的in[y * width + x],然后写入输出矩阵的out[x * width + y],即交换行列索引。线程坐标通过blockIdx和threadIdx计算,并检查边界条件。

如何用nvprof查看CUDA程序的性能?

使用nvprof工具可以查看CUDA程序的性能。在命令行中执行:sudo /usr/local/cuda/bin/nvprof ./可执行文件。例如,对于矩阵乘法程序,可以运行sudo /usr/local/cuda/bin/nvprof ./matrix_mul来获取性能分析数据。

如何用CUDA将RGB图像转换为灰度图?

将RGB图像转换为灰度图的CUDA核函数中,每个线程处理一个像素:读取uchar3类型的BGR值,计算灰度值out = 0.30 * R + 0.59 * G + 0.11 * B,其中R、G、B分别对应bgr.z、bgr.y、bgr.x。然后写入输出图像。主机端使用OpenCV读取图像并分配内存,最后保存灰度图。

🏷️

标签

➡️

继续阅读