CUDA 矩阵乘法优化:从朴素实现到 Shared Memory 分块

光通信老兵 发表于 2026-10-13 06:04 · 17 次浏览 · 2 条回复
光
矩阵乘法(GEMM)是理解 CUDA 优化最好的练习。本帖以 C = A × B 为例,梳理从朴素实现到分块优化的步骤,与 Shared Memory 基础帖互为补充。

一、朴素实现
每个线程计算 C 的一个元素,循环读取 A 的一行和 B 的一列。问题在于每个元素被重复从全局内存读取 N 次,算术强度很低,性能通常只有峰值的几个百分点。

二、Shared Memory 分块(tiling)
1. 每个 block 负责 C 的一个 TILE×TILE 子块(常用 16 或 32);
2. 沿 K 维循环,每次把 A、B 各一个子块载入 shared memory;
3. __syncthreads() 后做子块乘加,再同步进入下一轮;
4. 全局内存访问量降为原来的 1/TILE。

三、进一步优化
1. 避免 bank conflict:A 子块按需转置存放或填充一列,让 warp 内访问落在不同 bank;
2. 寄存器分块:每线程计算 4×4 或 8×8 个输出,提升数据复用;
3. 向量化加载:使用 float4 一次读 16 字节;
4. 双缓冲:计算当前子块时预取下一个子块,隐藏访存延迟;
5. Tensor Core:使用 WMMA 或 MMA 指令,FP16/BF16 下吞吐提高数倍,需要按指定布局在 shared memory 中重排数据。

四、常见坑
1. 矩阵尺寸不是 TILE 整数倍时,边界判断遗漏导致越界;
2. 共享内存过大导致占用率下降,性能反而变差;
3. 自己写的 kernel 与 cuBLAS 差距大,生产环境建议优先用 cuBLAS/CUTLASS。

讨论:
1. 你们手写 GEMM 能做到 cuBLAS 的百分之多少?
2. Tensor Core 的数据重排开销你们怎么优化?
广告位 A8广告位招商帖子页首楼下方通栏 · 728×90 · 查看报价 · 联系 ads@oeforum.com
F
矩阵乘法再往下优化的话,可以试试把 A 矩阵转置后放 shared memory,让访问变成行对齐,能减不少 bank conflict。一般还能再榨出 10~20%。
嵌
提醒一下 tensor core 和 shared memory 的配合:tensor core 的输入需要按特定 layout 排布,用 shared memory 做数据重排是很常见的做法,但重排本身的访存开销不能忽略。
登录 后参与回复,还没有账号?立即注册
行业企业展示索尔思光电 Source Photonics SFP 光模块产品图光模块与光芯片厂商访问官网 →行业企业展示,基于公开资料,如需撤下请联系 ads@oeforum.com