PyTorch CUDA 环境变量完全指南:显存缓存、fork 安全检查与 cuDNN/cuBLAS 运行期调优
PyTorch CUDA 环境变量完全指南显存缓存、fork 安全检查与 cuDNN/cuBLAS 运行期调优【免费下载链接】pytorchTensors and Dynamic neural networks in Python with strong GPU acceleration项目地址: https://gitcode.com/GitHub_Trending/py/pytorch本篇指南围绕 PyTorch 官方文档《CUDA Environment Variables》中的全部环境变量展开系统讲解两类变量一类是 PyTorch 自定义、控制框架内部行为的变量如 CUDA 内存缓存、cuDNN v8 API、NCCL 通信、TF32 精度开关另一类是 CUDA Runtime 及 cuBLAS/cuDNN 等底层库的变量如设备可见性、同步模式、workspace 配置。读完本文你将掌握每个变量的语义、默认行为、适用调试/调优场景并能结合源码确认其生效路径。总览先按作用域分清两类环境变量CUDA 生态的调试与调优往往通过环境变量完成其作用域可以粗略分为两层PyTorch 层以PYTORCH_*与TORCH_*为前缀由 PyTorch 框架自身读取控制 CUDACachingAllocator、cuDNN 调用后端、NCCL 通信组、全局浮点精度等CUDA Runtime 与库层以CUDA_*、CUBLAS*、CUDNN*、NVIDIA_*为前缀由 NVIDIA CUDA Driver/Runtime 或相关库直接读取决定设备可见范围、kernel 同步性、workspace 分配等。理解这一分层有助于快速定位问题例如进程崩溃或显存异常优先检查 PyTorch 层而 GPU 不可见、kernel 行为不确定等问题通常要检查 CUDA Runtime 层变量。本仓库的官方文档 cuda_environment_variables.md 即按此结构组织同时引用了 NVIDIA 官方 CUDA 编程指南作为底层参考。PyTorch 框架环境变量PYTORCH_NO_CUDA_MEMORY_CACHING关闭 CUDA 显存缓存设置为1时PyTorch 将禁用 CUDA 内存分配的缓存行为。默认情况下PyTorch 使用 CUDACachingAllocator显存块被释放后不会立刻归还给 CUDA Runtime而是缓存在 PyTorch 的分配器池中以供后续复用。这种设计大幅降低cudaMalloc的频繁调用开销但也让“释放”与“显存回落”之间存在时差给显存排查带来干扰。当你在调试显存泄漏、内存碎片或第三方工具观测显存曲线时可以临时开启PYTORCH_NO_CUDA_MEMORY_CACHING1 python your_script.py从源码使用看PyTorch 内存追踪工具mem_tracker.py会根据该变量是否为1来调整其内存统计粒度的假定说明它确实是影响分配器行为的一级开关。需要注意的是关闭缓存会显著降低反复分配/释放场景的性能因此它定位为“调试专用”不建议在性能敏感的生产训练脚本中长期开启。PYTORCH_ALLOC_CONF及其别名PYTORCH_CUDA_ALLOC_CONF精细配置 CUDA 缓存分配器该变量的作用是向 CUDACachingAllocator 传入一套key:value风格的配置。官方文档明确指出完整的深度说明见 {ref}cuda-memory-management章节即 notes/cuda.md 与 cuda.md 中关于 CUDA 内存管理的内容。同时PYTORCH_CUDA_ALLOC_CONF仅作为向后兼容的别名保留新代码请优先使用PYTORCH_ALLOC_CONF。从缓存分配器的实现CUDACachingAllocator.cpp可以确认该变量实际支持的若干关键键配置键说明依据实现源码expandable_segments:True/False启用“可扩展段”式分配让显存预留可以按需增长/收缩从实现注释看该模式是应对碎片化的关键选项但 IPC 共享等跨进程能力受限expandable_segments_reserve/expandable_segments_reserve_by_class控制可扩展段模式下的显存预留量超出预留时实现会打印提示建议调小预留expandable_segments_handle_type指定可扩展段的 IPC handle 类型例如posix_fd相关错误提示出现在 CUDACachingAllocator.cpp 的 IPC 共享路径中garbage_collection_threshold触发分配器垃圾回收的阈值回收逻辑位于 CUDACachingAllocator.cpp 的分配路径中典型用法# 以可扩展段模式运行缓解显存碎片 PYTORCH_ALLOC_CONFexpandable_segments:True python train.py # 同时指定多项配置使用冒号分隔的 key:value 序列 PYTORCH_ALLOC_CONFexpandable_segments:True,garbage_collection_threshold:0.8 python train.pyPyTorch 在快照/统计层面也会记录该配置缓存分配器模块与内存快照实现Module.cpp 与 memory_snapshot.cpp都会读取PYTORCH_CUDA_ALLOC_CONF并记录当时的分配器设置及expandable_segments状态便于事后复盘运行时配置。除了在命令行设置环境变量你还可以在代码中通过torch.cuda.memory._set_allocator_settings(...)动态调整分配器设置。PYTORCH_NVML_BASED_CUDA_CHECK用 NVML 探测 CUDA 可用性规避 fork 问题当设置为1时PyTorch 在导入会检查 CUDA 是否可用的模块之前会**改用 NVMLNVIDIA Management Library**来确认 CUDA driver 是否可用而不是走默认的 CUDA Runtime API 探测路径。该变量主要解决一个实际痛点CUDA Runtime 的初始化会污染 fork 出的子进程。默认实现中torch.cuda.is_available()通过torch._C._cuda_getDeviceCount()探测而后者会初始化 CUDA Driver APIcuInit在 fork 场景下子进程很可能因 CUDA 初始化错误而崩溃即官方文档注释中提到的 fork poisoning。源码 torch/cuda/init.py 给出了精确语义def _nvml_based_avail() - bool: return os.getenv(PYTORCH_NVML_BASED_CUDA_CHECK) 1当该变量开启时走device_count() 0NVML 路径若 NVML 发现/初始化失败则会回退到默认的 CUDA Runtime API 评估cudaGetDeviceCount。代价是 NVML 路径对 CUDA 可用性的评估相对更弱但换来 fork 场景下的健壮性。使用方式PYTORCH_NVML_BASED_CUDA_CHECK1 python -c import torch; print(torch.cuda.is_available())在 torch/accelerator/init.py 的文档字符串中同样强调设置PYTORCH_NVML_BASED_CUDA_CHECK1后is_available()将不会污染 fork。TORCH_CUDNN_V8_API_LRU_CACHE_LIMIT限制 cuDNN v8 API 的缓存该变量限制 cuDNN v8 APIcudnnFrontend路线内部使用的 LRU 缓存条数。默认值为10000在假设每个 ExecutionPlan 约占用200KiB的前提下大致对应约2GiB内存占用。语义如下设为0不限缓存条数设为负值完全禁用缓存。相关解析逻辑在 Conv_v8.cpp实现会读取TORCH_CUDNN_V8_API_LRU_CACHE_LIMIT并校验其数值非法输入会打印“invalid TORCH_CUDNN_V8_API_LRU_CACHE_LIMIT”之类的警告。如果你的模型反复创建大量 cuDNN engine/plan 导致显存或主机内存占用偏高可尝试# 缩小缓存 TORCH_CUDNN_V8_API_LRU_CACHE_LIMIT1000 python your_script.py # 彻底关闭 plan 缓存牺牲重复调用时的命中收益 TORCH_CUDNN_V8_API_LRU_CACHE_LIMIT-1 python your_script.pyTORCH_CUDNN_V8_API_DISABLED回退到 cuDNN v7 API设置为1时PyTorch 将禁用 cuDNN v8 APIconvolution 前端走 v7 实现。该开关的读取点在 ConvUtils.hstatic bool cudnnv8_flag c10::utils::check_env(TORCH_CUDNN_V8_API_DISABLED) ! true;并在 ConvShared.h 的注释中明确说明该变量的用途。v8 API 提供了更灵活且通常更快的 plan 选择能力但如果你在某个 cuDNN 版本上遇到 v8 路径的异常行为、不确定的数值或崩溃官方建议先以该变量回退到 v7 API 做交叉验证TORCH_CUDNN_V8_API_DISABLED1 python your_script.py注意这是运行期的行为开关与编译期是否链接 cuDNN v8 无关——仓库代码在运行时才根据环境变量决定使用哪个 API 路线。TORCH_CUDNN_V8_API_DEBUG核对是否真的在使用 v8设置为1时启用“sanity check”用于确认 cuDNN V8 是否真的被使用。在 ConvUtils.h 中它被显式读取并且在 v8 判定启用时会通过TORCH_WARN打印类似“TORCH_CUDNN_V8_DEBUG ON, V8 ON: ...”的日志附带TORCH_CUDNN_V8_API_DISABLED与启发式模式的状态便于你快速定位当前到底走了哪条卷积后端路径TORCH_CUDNN_V8_API_DEBUG1 python your_script.py 21 | grep -i v8它与TORCH_CUDNN_V8_API_DISABLED配合使用效果最佳一个负责关闭一个负责确认关闭是否生效。TORCH_ALLOW_TF32_CUBLAS_OVERRIDE强制覆盖 TF32 开关若设置为1将强制启用TF32 精度并覆盖通过torch.set_float32_matmul_precision()设置的精度偏好。TF32 是 NVIDIA Ampere 及之后架构上的一个折中精度以float32输入、约 10 bit 尾数参与矩阵乘换取更高的吞吐但会引入一定数值误差。这一“覆盖”变量的意义在于当代码库内部或第三方库将 matmul 精度显式设为非 TF32 时你不需要改动任何 Python 代码仅靠环境变量即可在不改代码的前提下强制让 cuBLAS 矩阵乘回到 TF32 加速路径适合对数值要求不苛刻、希望统一压测吞吐的场景TORCH_ALLOW_TF32_CUBLAS_OVERRIDE1 python benchmark_matmul.pyTORCH_NCCL_USE_COMM_NONBLOCKING开启 NCCL 非阻塞错误处理若设置为1PyTorch 将启用 NCCL 的非阻塞错误处理。在多卡/多机分布式训练中NCCL 通信组发生异常时传统阻塞式处理容易让进程卡死或长时间等待。非阻塞模式下通信错误能够被更快地异步暴露出来。从源码看该变量在 PyTorch 分布式通信核心 ProcessGroupNCCL.cpp 中被读取并影响后端通信组的初始化与错误上报行为。使用方式TORCH_NCCL_USE_COMM_NONBLOCKING1 torchrun --nproc_per_node8 train_distributed.py如果你在分布式训练中遇到过“rank 掉线后整体挂死、错误迟迟不抛出”的现象可尝试开启本变量观察是否能在更早时机捕获通信失败。CUDA Runtime 与底层库环境变量CUDA_VISIBLE_DEVICES控制 GPU 可见性接受逗号分隔的 GPU 设备 ID 列表限定哪些物理 GPU 会被 CUDA Runtime 暴露给进程。设置后进程内 CUDA 设备编号将按该列表重新索引设置为-1时则不暴露任何 GPU等价于进程视为无 GPU。# 只暴露物理 GPU 2 与 5进程内编号为 0、1 CUDA_VISIBLE_DEVICES2,5 python -c import torch; print(torch.cuda.device_count()) # 完全隐藏 GPU常用于强制走 CPU 路径验证逻辑 CUDA_VISIBLE_DEVICES-1 python -c import torch; print(torch.cuda.is_available())注意CUDA_VISIBLE_DEVICES的语义是“可见性过滤”而非“任务分配”它由 CUDA Runtime 在进程启动早期解析因此在 shell 启动命令处设置而非脚本运行中途修改才能可靠生效。CUDA_LAUNCH_BLOCKING让所有 CUDA kernel 同步执行设置为1时所有 CUDA kernel 启动都会同步等待完成代码表现为“每个 kernel 都像阻塞调用”。这会大幅降低吞吐但换来确定性的执行顺序与精确的崩溃/报错定位——异步 kernel 的报错通常延迟到后续同步点才抛出难以定位是哪一次 launch 引发的。CUDA_LAUNCH_BLOCKING1 python your_script.py当调试 Illegal memory access、cuda assertion 等难缠问题时该变量几乎是最先应启用的诊断开关之一与PYTORCH_NO_CUDA_MEMORY_CACHING1组合可以构成一套基础 CUDA 诊断环境。cuBLAS/cuDNN 的 workspace 配置三件套cuBLAS/cuDNN 的许多 kernel 需要一块临时 workspace 内存来运行非确定性或特定算法。控制这块内存的变量有三个CUBLAS_WORKSPACE_CONFIG用于按“每次分配”设置 cuBLAS 的 workspace 配置。格式为:[SIZE]:[COUNT]可重复段组合。官方默认值CUBLAS_WORKSPACE_CONFIG:4096:2:16:8含义是总 workspace 2 * 4096 KiB 8 * 16 KiB即 2 块 4MiB 加上 8 块 16KiB。若希望强制 cuBLAS不使用任何 workspace可设置CUBLAS_WORKSPACE_CONFIG:0:0该变量与数值可复现性高度相关cuBLAS 某些算法会依据可用 workspace 大小选择不同实现进而产生不同数值结果因此官方在讨论确定性与 benchmark 时通常建议统一配置它。CUDNN_CONV_WSCAP_DBG与CUBLAS_WORKSPACE_CONFIG类似用于设置 cuDNN 每次分配可用的 workspace 上限属于面向调试DBG的约束手段。当你希望约束 cuDNN 卷积算法对显存的占用时可据此收缩其 workspace 预算。CUBLASLT_WORKSPACE_SIZE用于设置 cuBLASLtcuBLAS Lightweight API常用于自定义 matmul/epilogue 场景的 workspace 大小。三者覆盖了 PyTorch 矩阵乘与卷积在不同 cuBLAS/cuDNN 实现路线上的 workspace 控制需求。CUDNN_ERRATA_JSON_FILE注入 errata filter 文件该变量指向一个 errata filter 的 JSON 文件路径。cuDNN 在启发式/自动调优时可能会选中某些已知存在数值或行为问题的 engine configerrata filter 可让 cuDNN 跳过这些特定配置主要用于规避已知有问题的 engine将自动调优结果“硬编码”固定下来以获得跨运行的稳定复现。CUDNN_ERRATA_JSON_FILE/path/to/errata.json python your_script.py由于 errata 文件格式与 cuDNN 版本强相关实际使用时请以你所用 cuDNN 版本对应 SDK 的说明为准。NVIDIA_TF32_OVERRIDE全局级 TF32 总开关若设置为0将在全局范围内禁用所有 kernel 的 TF32并且优先级高于 PyTorch 侧的任何设置包括torch.backends.cuda.matmul.allow_tf32、torch.backends.cudnn.allow_tf32、set_float32_matmul_precision以及上文提到的TORCH_ALLOW_TF32_CUBLAS_OVERRIDE。它是 NVIDIA 层面兜底性的“一票否决”开关适合在验证数值正确性、追求最高精度时使用NVIDIA_TF32_OVERRIDE0 python your_script.py把它与 PyTorch 层的TORCH_ALLOW_TF32_CUBLAS_OVERRIDE放在一起看能更清楚地理解 TF32 的“开关层级”NVIDIA_TF32_OVERRIDE0是全局底线PyTorch 层变量只在 NVIDIA 全局未强制关闭的前提下才有意义。典型组合常用调试与调优速查将上述变量按场景组合可以得到几条高频使用的“配方”CUDA 崩溃 / 数值非法NaN、Illegal memory access定位CUDA_LAUNCH_BLOCKING1 \ PYTORCH_NO_CUDA_MEMORY_CACHING1 \ NVIDIA_TF32_OVERRIDE0 \ python reproduce_crash.py需要确定性deterministic数值的复现固定 workspace 配置并关闭 TF32CUBLAS_WORKSPACE_CONFIG:0:0 \ NVIDIA_TF32_OVERRIDE0 \ python reproduce_benchmark.py多进程 / fork 场景 CUDA 不可用排查PYTORCH_NVML_BASED_CUDA_CHECK1 python -c import torch; print(torch.cuda.is_available())分布式训练通信异常提前暴露TORCH_NCCL_USE_COMM_NONBLOCKING1 torchrun --nnodes... --nproc_per_node... train.py如何快速确认变量是否真的生效环境变量是否生效可以通过两条途径核实观察框架行为例如设置TORCH_CUDNN_V8_API_DEBUG1后stderr 会出现与 v8 状态相关的TORCH_WARN日志直接确认卷积后端选路设置PYTORCH_NVML_BASED_CUDA_CHECK1后可通过阅读 torch/cuda/init.py 理解为何is_available()不再走cudaGetDeviceCount。直接阅读源码读取点本仓库中上述变量均有明确读取位置例如ConvUtils.hTORCH_CUDNN_V8_API_DISABLED、TORCH_CUDNN_V8_API_DEBUGConv_v8.cppTORCH_CUDNN_V8_API_LRU_CACHE_LIMITProcessGroupNCCL.cppTORCH_NCCL_USE_COMM_NONBLOCKINGmem_tracker.pyPYTORCH_NO_CUDA_MEMORY_CACHING。在自行扩展新变量或排查不生效原因时建议先在整个torch/与c10/目录内搜索变量名确认其读取时机进程启动早期读取的变量往往不能在中途动态切换。延伸阅读官方环境变量速查表docs/source/cuda_environment_variables.mdCUDA 内存管理深度说明对应PYTORCH_ALLOC_CONF的 {ref}cuda-memory-management章节docs/source/notes/cuda.md 与 docs/source/cuda.md多进程与 CUDA fork 问题相关讨论docs/source/notes/faq.mdCUDA 缓存分配器实现c10/cuda/CUDACachingAllocator.cpp【免费下载链接】pytorchTensors and Dynamic neural networks in Python with strong GPU acceleration项目地址: https://gitcode.com/GitHub_Trending/py/pytorch创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →