CUDA Toolkit如何管理内存

GPU
小华
2025-11-27

CUDA Toolkit 内存管理全景
一 核心内存空间与生命周期

  • 全局内存 Global Memory:所有线程可访问,位于GPU显存,容量大但访问延迟高;生命周期贯穿程序运行,需由开发者显式分配与释放。
  • 共享内存 Shared Memory:位于每个 SM 上,线程块内共享,访问延迟低、带宽高,容量小,需手动分块与同步。
  • 常量内存 Constant Memory:只读,缓存于各 SM 的常量缓存,适合广播式只读数据。
  • 纹理内存 Texture Memory:只读,具备多种寻址与滤波模式,适合空间局部性强的访问。
  • 本地内存 Local Memory:线程私有,通常映射到全局内存,用于寄存器溢出或编译器无法放入寄存器的变量。
  • 小结:全局/常量/纹理/本地由 CUDA 运行时与硬件管理其分配与可见性;共享内存由程序员在核函数中声明并使用。上述内存类型共同构成 CUDA 的层次化内存模型,是性能优化的基础。

二 分配释放与数据传输 API

  • 设备端分配与释放
  • cudaMalloc(void devPtr, size_t count):在设备上分配 count 字节的全局内存。
  • cudaFree(void devPtr):释放先前分配的设备内存。
  • cudaMemset(void devPtr, int value, size_t count):以指定值填充设备内存。
  • 主机与设备间传输
  • cudaMemcpy(void dst, const void src, size_t count, cudaMemcpyKind kind):在主机与设备间复制数据,kind 可为 cudaMemcpyHostToDevice / DeviceToHost / DeviceToDevice / HostToHost
  • 固定主机内存(Pinned/Paged-locked)
  • cudaMallocHost(void ptr, size_t count):分配页面锁定主机内存,可被设备直接访问,H2D/D2H 吞吐更高。
  • cudaFreeHost(void ptr):释放固定内存。
  • 零拷贝内存(Mapped Pinned)
  • 通过 cudaHostAlloc(…, cudaHostAllocMapped) 分配,主机与设备均可直接访问同一映射内存;需做好同步,实际通过 PCIe 远程访问,延迟高、带宽低,适合小数据或调试。
  • 统一内存(Unified Memory, UM)
  • cudaMallocManaged(void devPtr, size_t size, unsigned int flags = 0):分配托管内存,在 CPU/GPU 间共享同一指针,底层自动迁移数据;简化编程,但性能可能波动。
  • 统一虚拟地址 UVA
  • CUDA 4.0 起在 64 位系统上提供,使主机与设备共享统一虚拟地址空间,便于指针在 CPU/GPU 间直接传递与比较。
  • 性能要点
  • PCIe 带宽远低于显存带宽(例如:PCIe Gen2 ≈ 8 GB/s,而 Fermi C2050 GDDR5 ≈ 144 GB/s),应尽量减少主机与设备之间的传输。
  • cudaMalloc/cudaFree 开销较高,建议复用设备内存以降低分配成本。

三 访问模式与带宽利用

  • 线程束(warp,32 线程)按单条内存请求发出访问;全局内存通过缓存服务,常见事务粒度为128 字节(两级缓存均用)或32 字节(仅二级缓存)。
  • 对齐与合并
  • 对齐访问:事务首地址为缓存粒度的偶数倍(如 128B/32B)更高效。
  • 合并访问:线程束访问连续地址块时,可用最少事务满足需求,带宽利用率最高。
  • 优化原则
  • 组织数据布局与访问顺序,使线程束访问对齐且连续;必要时利用共享内存/常量内存/纹理内存作为高速缓存,减少全局内存压力。

四 框架层的内存管理实践(以 PyTorch 为例)

  • 缓存分配器与延迟释放
  • PyTorch 维护 GPU 缓存分配器,对已释放显存进行池化与复用,减少频繁 cudaMalloc/cudaFree 的系统开销,并缓解碎片化
  • 监控与诊断
  • 使用 torch.cuda.memory_allocated() / memory_reserved() 观察分配与保留显存;配合 nvidia-smiPyTorch ProfilerNsight Systems 定位瓶颈。
  • 释放与回收
  • 删除不再使用的张量(如 del x),必要时调用 torch.cuda.empty_cache() 清理未使用缓存块(注意:不会释放被张量占用的“已保留”内存)。
  • 计算图与推理
  • 推理或截断图时用 torch.no_grad();循环中避免无谓的图累积,必要时 detach()
  • 环境与多进程
  • 通过环境变量如 PYTORCH_CUDA_ALLOC_CONF 调整分配器策略;多进程训练优先 spawn 启动方式,避免显存状态继承问题。
  • 典型优化组合
  • 混合精度训练(FP16/BF16)梯度检查点动态批处理、必要时 CPU/NVMe Offloading,在显存受限场景显著降低占用并维持吞吐。

五 选型与性能建议

  • 大数据高吞吐传输:优先使用普通主机内存 + cudaMemcpy,并批量合并小传输;必要时用固定内存提升 H2D/D2H 带宽。
  • 简化开发与通用共享:使用统一内存(cudaMallocManaged),注意其自动迁移可能带来性能波动。
  • 小数据/调试或主机内存充足:考虑零拷贝(cudaHostAllocMapped),但需接受高延迟/低带宽
  • 极致带宽与可控性:坚持显存驻留 + 合并访问 + 共享内存/纹理等 GPU 侧优化,尽量减少跨总线传输。
亿速云提供售前/售后服务

售前业务咨询

售后技术保障

400-100-2938

7*24小时售后电话

官方微信小程序