CUDA 10 · 库、多 GPU、项目与进阶路线

先用库,再决定是否写 Kernel

需求
├─ 高层框架已有高质量算子?         → 使用并 profile
├─ CUDA-X/CCCL/CUTLASS 已覆盖?      → 使用库,配置 stream/layout/workspace
├─ 能通过组合 + Graph 达到目标?      → 组合并捕获
├─ 需要融合/特殊布局/特殊语义?       → 自定义 kernel
└─ 需要架构极限或新指令研究?         → CUTLASS/CuTe/PTX + 专属 dispatch

成熟库通常已经处理多代架构、边界 shape、数值细节和算法选择。手写版本应先与库建立 correctness 和性能基线。

CUDA 生态地图

库/组件领域常见用途
cuBLAS / cuBLASLt稠密线性代数GEMM、batched GEMM、epilogue
cuSPARSE稀疏线性代数SpMV/SpMM、稀疏格式转换
cuSOLVER稠密/稀疏求解LU/QR/SVD/eigensolver
cuFFTFFT信号、卷积、谱方法
cuRAND随机数host/device RNG
cuDNN深度学习 primitivesconvolution、attention、norm 等
NCCL多 GPU collectiveall-reduce、all-gather、reduce-scatter
NPP / nvJPEG图像与编解码图像处理、JPEG pipeline
CUBCUDA 并行 primitiveswarp/block/device reduce、scan、sort
ThrustC++ 并行算法容器、iterator、transform/sort/scan
libcu++CUDA C++ 标准库扩展atomic、barrier、pipeline、标准设施
CUTLASS / CuTe矩阵 kernel 组件GEMM、layout、Tensor Core、fusion

CUB、Thrust 与 libcu++ 统一在 CCCL(CUDA C++ Core Libraries)生态下。CUB 的 warp/block/device 分层尤其适合自定义 kernel 内部复用。

Library 集成检查表

  • handle 是否绑定到正确 stream;
  • 输入/输出 layout、leading dimension、stride 是否准确;
  • host pointer mode 还是 device pointer mode;
  • workspace 的大小、对齐、生命周期;
  • 算法是否要求特定对齐、dtype、CC;
  • 是否允许 TF32/降精度/非确定性算法;
  • capture 到 CUDA Graph 时该 API 是否支持;
  • handle 是否在线程间安全共享;
  • 错误状态是否检查;
  • benchmark 是否包含 heuristic/autotune 的一次性成本。

多 GPU 的三层问题

算法层:数据并行 / 张量并行 / 流水线并行 / 任务并行
通信层:P2P copy / collective / host staging / 网络
拓扑层:PCIe switch / NVLink / NVSwitch / NUMA / NIC affinity

多 GPU 不是把 device_count 乘上去。通信量、同步点、拓扑和负载均衡决定可扩展性。

显式设备管理

int count = 0;
cudaGetDeviceCount(&count);

for (int d = 0; d < count; ++d) {
  cudaSetDevice(d);
  cudaDeviceProp p{};
  cudaGetDeviceProperties(&p, d);
  // 每个 device 分别创建 stream、event、allocation、library handle。
}

CUDA 对象通常与创建它的 device/context 有关联。多 host thread 管多 GPU 时,在线程开头显式 cudaSetDevice,不要依赖之前调用遗留的 current device。

Peer-to-Peer 与拓扑

int can = 0;
cudaDeviceCanAccessPeer(&can, dst, src);
if (can) {
  cudaSetDevice(dst);
  cudaDeviceEnablePeerAccess(src, 0);
}

随后可使用 peer copy 或在受支持条件下访问 peer memory。P2P 可用不等于一定走最高速 NVLink,也不等于任意访问模式都高效;使用 nvidia-smi topo -m、NVML 和 Systems 验证实际拓扑与路径。

若 P2P 不可用,Runtime 可能需要 host staging,带宽和同步行为会不同。跨 NUMA CPU socket 的 pinned buffer 也应考虑内存亲和性。

Collective 与通信复杂度

训练中常见:

Collective语义用例
AllReduce每个 rank 获得归约后的完整结果数据并行梯度
ReduceScatter归约后每个 rank 保留一个分片ZeRO/分片训练
AllGather收集所有 rank 的分片参数/激活重构
Broadcastroot 向所有 rank 发送初始化、模型同步
AllToAll每个 rank 向所有 rank 发送不同分片MoE token dispatch

NCCL 会按拓扑和消息规模选择算法/协议。优化重点不是自己重写 ring,而是:

  • 减少通信字节(分片、压缩、低精度);
  • 将大通信拆分并与计算重叠;
  • 避免过细 collective;
  • 正确设置 rank-device 映射与拓扑;
  • 用 Systems/NCCL tracing 找关键路径;
  • 保证所有 rank 以一致顺序调用 collective,避免死锁。

扩展效率

强扩展:总问题规模固定,GPU 增加;通信和串行部分最终主导。Amdahl 近似:

S(p)=1s+(1−s)/pS(p)=\frac{1}{s+(1-s)/p}

弱扩展:每 GPU 工作量固定,总问题规模随 GPU 增长;更关注通信增长和负载均衡。报告多 GPU 性能时至少给出:单卡基线、全局/每卡 batch、吞吐、延迟、通信占比和 scaling efficiency。

生产级 C++ 资源管理

使用 RAII 封装 device memory、stream、event 和 library handle,避免异常/早退泄漏:

class CudaStream {
 public:
  CudaStream() { CUDA_CHECK(cudaStreamCreateWithFlags(&s_, cudaStreamNonBlocking)); }
  ~CudaStream() { if (s_) cudaStreamDestroy(s_); }
  CudaStream(const CudaStream&) = delete;
  CudaStream& operator=(const CudaStream&) = delete;
  CudaStream(CudaStream&& other) noexcept : s_(other.s_) { other.s_ = nullptr; }
  cudaStream_t get() const { return s_; }
 private:
  cudaStream_t s_{};
};

析构函数不能安全抛异常;异步工作与资源析构的先后必须由所有权协议保证。高频 allocation 使用内存池,长期 buffer 使用显式生命周期,避免隐式 device-wide 同步。

推荐工程结构

cuda-project/
├─ CMakeLists.txt
├─ include/
│  ├─ cuda_check.hpp
│  └─ ops.hpp
├─ src/
│  ├─ ops.cu              # dispatch + kernels
│  ├─ reference.cpp       # CPU reference
│  └─ main.cpp
├─ tests/
│  ├─ correctness.cpp
│  └─ sanitizer_cases.cpp
├─ benchmarks/
│  └─ bench_ops.cpp
└─ scripts/
   ├─ profile_systems.*
   └─ profile_compute.*

每个算子至少有:

  1. 清晰的 shape/dtype/layout/aliasing 合同;
  2. CPU 或可信库 reference;
  3. 边界和随机 correctness test;
  4. 独立 benchmark;
  5. profile 入口;
  6. 支持架构与 fallback;
  7. 数值精度和确定性说明。

架构 Dispatch

不要在业务各处散落 if (cc >= ...)。集中注册:

op()
├─ capability / dtype / shape 检查
├─ Blackwell/Hopper specialized path(若编译且设备支持)
├─ Ampere+ async-copy path
├─ portable baseline CUDA path
└─ unsupported → 明确错误或 CPU/library fallback

编译时 __CUDA_ARCH__ 只在 device 编译阶段定义;host dispatch 应读取 device attributes。a/f 架构目标的兼容范围更窄,应保留 baseline code object 或独立二进制策略。

高级能力地图

能力什么时候需要先掌握什么
Driver API / NVRTC动态加载、运行时编译、插件Runtime、context/module 生命周期
CUDA Graph重复任务图、短 kernel 密集stream/event 与资源生命周期
Cooperative launchgrid 级同步occupancy、所有 block 同时驻留约束
Dynamic Parallelismdevice 侧动态启动launch 成本、嵌套同步;通常先考虑其他调度
Virtual Memory Management大型地址空间、稀疏映射、共享allocation/VA/physical mapping
IPC跨进程共享 memory/eventcontext、安全与生命周期
Cluster/DSMHopper+ block 集群协作block 模型、cluster occupancy
TMAHopper+ 多维异步搬运tiling、barrier、pipeline
Memory sync domainsHopper+ 隔离本地与远程流量的 fence 干扰CUDA memory model、system scope

高级特性不是学习清单上的勋章。只有当基础 profile 指向它解决的问题时再引入。

四个递进项目

项目 1:图像处理流水线

  • RGB→Gray、Gaussian blur、Sobel;
  • global-only 与 shared halo 对照;
  • pinned memory + streams 重叠批量图像;
  • CUDA Graph replay;
  • 指标:吞吐、端到端延迟、有效带宽。

项目 2:并行 primitives

  • reduce、scan、histogram、compact;
  • 自写版对照 CUB;
  • 测均匀/热点/边界输入;
  • Sanitizer 与浮点误差报告。

项目 3:GEMM 与 fused epilogue

  • naive → shared tile → register tile;
  • 对照 cuBLAS;
  • 用 cuBLASLt 实现 bias + activation;
  • 解释 Roofline 位置和资源限制。

项目 4:多 GPU mini-system

  • 每卡独立 stream 与 buffer;
  • P2P 或 NCCL AllReduce;
  • 计算/通信 overlap;
  • Systems 时间线标注 NVTX;
  • 报告 1/2/4/8 卡 scaling efficiency。

12 周学习计划

周主题交付物
1工具链、vector add、错误检查可编译工程 + device query
2SIMT、索引、grid-stride一维/二维 kernel
3合并访存、布局、带宽copy/transpose benchmark
4shared、bank、warp primitivetiled transpose + block reduce
5reduce/scan/histogram自写与 CUB 对照
6stream/event/pinned三阶段 pipeline 时间线
7Graph/async allocator重复工作流 benchmark
8naive/tiled GEMMcorrectness + GFLOP/s
9register tile/Tensor Core 生态cuBLASLt/CUTLASS 对照
10Roofline/Nsight完整性能分析报告
11多 GPU/NCCLscaling 报告
12综合项目文档、测试、benchmark、profile 全套

速查:遇到问题先去哪一章

问题章节
编译、架构目标、PTX/cubin01
warp、SM、occupancy 基础02
index、block shape、warp primitive03
coalescing、shared、managed/pinned04
race、atomic、stream、event、graph05
reduce/scan/histogram/stencil06
GEMM、Tensor Core、Attention07
Roofline、stall、调参08
Sanitizer、Nsight、数值验证09
CUDA-X、多 GPU、工程化本章
CUDA C++、低精度、内存模型11
CUDA Python、DLPack、跨语言 stream12
CUDA Tile13
Unified Memory、memory pool、VMM14
Cluster、DSM、TMA、高级异步15
Driver API、NVRTC、部署兼容16
CUDA-X 库调用范式17
图像、Monte Carlo、BFS、Attention 案例与术语18
MIG/MPS、Green Context、fabric、图形互操作19

官方参考总表