CUDA-Samples cuBLAS 示例实践矩阵乘法 GPU 性能的 3 个决策点【免费下载链接】cuda-samplesSamples for CUDA Developers which demonstrates features in CUDA Toolkit项目地址: https://gitcode.com/GitHub_Trending/cu/cuda-samples场景切入批处理图像滤波GEMM 吞吐差在哪批处理图像管线里每一轮滤波或卷积本质上是向 GPU 投喂一次 GEMM通用矩阵乘法。NVIDIA CUDA-Samples 在cpp/4_CUDA_Libraries/下提供 simpleCUBLAS、matrixMulCUBLAS、batchCUBLAS 三个示例恰好覆盖调用序列、内存布局、批量并发三层是 GPU 端矩阵运算优化的入口。本文按三个独立决策点拆解每个结论都可回溯到源码文件。示例地图三个 cuBLAS 示例的入口 三个示例同属cpp/4_CUDA_Libraries/解决的问题互不重叠先看表再选阅读顺序示例回答的问题仓库路径关键 APIsimpleCUBLAS一次 GEMM 的调用链路是否正确275×275 单矩阵 CPU 三重循环对照cpp/4_CUDA_Libraries/simpleCUBLAS/cublasSgemm、cublasSetVectormatrixMulCUBLAS行主序数据如何免转置喂给列主序的 cuBLAS以及 GPU 侧计时方法cpp/4_CUDA_Libraries/matrixMulCUBLAS/cublasSgemmB、A 逆序、cudaEvent 计时batchCUBLASN 个小 GEMM 如何一次跑完regular / streams / batched 三模式对照cpp/4_CUDA_Libraries/batchCUBLAS/cublasSgemmBatched、cublasSetStreamcuBLAS 句柄与 GEMM 调用序列怎么定cublasHandle_t是有状态对象内部持有设备、流和数学模式。创建成本不低涉及内核选择表初始化所以边界条件很清晰长驻服务进程启动时cublasCreate一次handle 生命周期与进程一致不要按请求反复创建/销毁短离线作业程序入口创建、退出前cublasDestroysimpleCUBLAS 就是这个模式需要 CPU 参照值做校验时保留 host 端矩阵副本用cublasSetVector/cublasGetVector上传下载数据已在 GPU 管线内部、无需与 CPU 比对时这两步可并入管线直接用cudaMemcpy或免拷贝。调用序列是固定的五步simpleCUBLAS 的关键行如下摘自 simpleCUBLAS.cpp 第 96、149、175、191、238 行status cublasCreate(handle); status cublasSetVector(n2, sizeof(h_A[0]), h_A, 1, d_A, 1); status cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, N, N, N, alpha, d_A, N, d_B, N, beta, d_C, N); status cublasGetVector(n2, sizeof(h_C[0]), d_C, 1, h_C, 1); status cublasDestroy(handle);正确性判定也值得注意simpleCUBLAS 用相对 L2 误差error_norm / ref_norm 1e-6f判定通过第 245 行而不是逐元素相等——float GEMM 的累加顺序与 CPU 不同逐位相等永远做不到。cuBLAS 列优先存储下如何免转置cuBLAS 按列主序解释指针。把一个行主序的 C 数组直接传进去它在 cuBLAS 眼里就是该矩阵的转置——这个隐式转置是新手踩坑的高发点。matrixMulCUBLAS.cpp 的文件头注释第 36-57 行给出了完整推导结论只有一条行主序的 C A·B按 (B, A) 逆序调用即可等价于列主序下的 Cᵀ Bᵀ·Aᵀ不需要任何显式转置核或额外内存流量。// 行主序 C A*B → 列主序 C^T B^T*A^T故参数顺序换为 d_B, d_A checkCudaErrors(cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, matrix_size.uiWB, matrix_size.uiHA, matrix_size.uiWA, alpha, d_B, matrix_size.uiWB, d_A, matrix_size.uiWA, beta, d_C, matrix_size.uiWB));注意三个维度和 leading dimension 的对应关系行主序 A 是uiHA×uiWA传进去后在 cuBLAS 眼里是uiWA×uiHA的 Aᵀ所以lda uiWA结果矩阵 C 的ldc uiWB同理。边界条件数据由 GPU 侧直接按列主序生成比如上游算子输出就是列主序按自然顺序 (A, B) 调用不要换序行主序 C 数组且布局不可改换序 (B, A)零拷贝优先于一切转置方案确实需要另一种逻辑转置如 Aᵀ·B用transa/transb CUBLAS_OP_T并同步调整 m/n/k 与 ld——此时 ld 取原矩阵的行数与换序方案不是一回事。batched API 与流并发的适用规模batchCUBLAS 在同一组输入上跑三种模式tmRegular同一默认流串行 N 次 GEMM、tmStream每个 GEMM 一条独立流、tmBatched一次cublasSgemmBatched默认矩阵 128×128×128、N10可用-m/-n/-k/-N覆盖。它打印的正是三种模式各自的elapsed与 GFLOPS对照关系要自己按机器跑出来但决策边界可以从实现里读出来// batched 模式指针数组本身必须在 device 端 cublasSetStream(handle, streamArray[0]); status1 cublasXgemmBatched(handle, params.transa, params.transb, params.m, params.n, params.k, params.alpha, (const T_ELEM **)devPtrA_dev, rowsA, (const T_ELEM **)devPtrB_dev, rowsB, params.beta, devPtrC_dev, rowsC, opts.N);边界条件N 个小矩阵、尺寸统一选 batched。单 GEMM 小到不足以喂满 GPU128³ 的 sgemm 是微秒级时合并成一次调用摊薄启动开销收益最大N 个矩阵尺寸不一batched 不可用m/n/k/ld 全部相同退回多流并发——cublasSetStream(handle, streamArray[i])后逐个派发前提是每个 GEMM 之间无数据依赖单矩阵已大到饱和算力两者都不必上单次cublasSgemm即可batched 只会多一次 N×3 个指针的 H2D 拷贝batchCUBLAS.cpp 第 451-463 行就是为这件事额外cudaMalloccudaMemcpy指针数组。数据与可复现三个示例内置的对比配置三个示例都不读外部数据文件输入由rand()/RAND_MAX在代码内生成matrixMulCUBLAS 固定srand(2006)结果可复现。各自内置的测量与校验配置如下配置项simpleCUBLASmatrixMulCUBLASbatchCUBLAS矩阵规模275×275方阵默认 sizemult5A 640×480、B 480×320、C 640×32032 块对齐128×128×128迭代 / 批量1 次nIter30N10跑 regular/streams/batched 三组预热无计时 event 开始前额外执行 1 次 GEMM无计时方式不计时cudaEventRecord/cudaEventElapsedTime输出 GFlop/sgettimeofday每组输出 elapsed 与 GFLOPSCPU 对照simple_sgemm三重循环float 累加matrixMulCPU三重循环double 累加无用 ULP/相对误差容忍度校验sgemm 相对误差 6e-6两个诚实性声明一是性能数字以示例自身 stdout 输出为准matrixMulCUBLAS 源码里就带着NOTE: The CUDA Samples are not meant for performance measurements的免责声明GPU Boost 会让结果漂移二是仓库的共享图像数据在Common/data/teapot512.pgm 等 8 个文件服务于纹理/图像类示例本组 cuBLAS 示例并未引用它们——下面这张图取自cpp/5_Domain_Specific/bilateralFilter/的真实样本数据用来说明图像即矩阵这一负载形态选型速查与常见坑 ⚠️换序写反行主序 CA·B 必须按 (B, A) 传参按 (A, B) 传输出整体等价于 Cᵀ每个元素位置全错且 L2 校验未必能立刻暴露——推导见 matrixMulCUBLAS.cpp 文件头。host 指针数组进 batched 会崩cublasSgemmBatched的 Aarray/Barray/Carray 必须已拷到 device 端batchCUBLAS.cpp 第 451-463 行。batched 的规模边界样本默认 128³、N10单矩阵大到已饱和算力时上 batched/多流只有成本没有收益。cublasSetStream是有状态调用多线程共用一个 handle 必须串行化否则流设置互相覆盖样本中每次派发前都重新 SetStreambatchCUBLAS.cpp 第 567 行。延伸阅读matrixMulCUBLAS.cpp文件头 20 行注释是行主序/列主序等价关系的完整推导动布局前先读它batchCUBLAS.cpp三种派发模式共用同一组测试参数是仓库里最干净的 A/B 对照写法simpleCUBLAS.cppCPU 参照实现simple_sgemm与相对 L2 误差判据cpp/4_CUDA_Libraries/README.md该目录下全部库示例的索引Common/data/仓库共享图像数据目录纹理与图像示例的输入源【免费下载链接】cuda-samplesSamples for CUDA Developers which demonstrates features in CUDA Toolkit项目地址: https://gitcode.com/GitHub_Trending/cu/cuda-samples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
