深度学习环境搭配以及CUDA的runtime
⚪正确的深度学习环境安装顺序
|
层级 |
内容 |
说明 |
|---|---|---|
|
1 |
显卡硬件 |
物理 GPU |
|
2 |
显卡驱动(NVIDIA Driver) |
让系统识别 GPU |
|
3 |
Miniconda |
Python 环境管理工具(你说的"mini-CUDA"其实是 Miniconda) |
|
4 |
在 conda 环境中装 PyTorch + CUDA |
PyTorch 会自带 cudatoolkit/cuda runtime |
日常做深度学习,系统级的 CUDA Toolkit 不是必须装的。用 conda/pip 装 PyTorch 时,它会自动拉取对应版本的 cuda runtime,这部分是独立于系统 CUDA 的。只有当你要编译 CUDA 代码(比如 MMCV 自定义算子、DCN、某些自编译的 CUDA kernel)时,才需要装完整的 CUDA Toolkit。
如何选 CUDA 版本(关键问题)
决策链:驱动版本 → 决定支持的最高 CUDA → 再从 PyTorch 官网挑一个
第一步:看驱动支持的最高 CUDA 版本
nvidia-smi
右上角 CUDA Version: 12.4 这个值,是驱动支持的最高 CUDA 版本,不是你已经装了的版本。你装的 CUDA 只要 ≤ 这个数就行。
第二步:去 PyTorch 官网看可选版本
https://pytorch.org/get-started/locally/
官网目前一般提供 CUDA 11.8 / 12.1 / 12.4 等选项。在驱动支持范围内,选一个官网提供的就行,不用追新。
第三步:考虑其他依赖的兼容性
如果你要用 MMCV、MMSegmentation、某些老版本 Restormer/BasicSR,它们对 CUDA/PyTorch 版本有要求,优先服从这些依赖。
推荐的实际流程
-
装显卡驱动(Linux 服务器通常已经装好,
nvidia-smi能出结果就行) -
装 Miniconda
-
conda create -n myenv python=3.10建环境 -
去 PyTorch 官网复制对应 CUDA 版本的安装命令,直接装
-
验证:
python -c "import torch; print(torch.cuda.is_available())"返回 True 就成了
两个 CUDA 相关命令的区别
|
命令 |
显示什么 |
|---|---|
|
|
驱动版本 + 驱动支持的最高 CUDA |
|
|
系统安装的 CUDA Toolkit 版本(没装就没有) |
什么是 CUDA Runtime
⚪Runtime = 运行时 = 程序跑起来时调用的那些动态库。
具体来说,就是这堆 .so/.dll 文件:
libcudart.so # CUDA 核心运行时
libcublas.so # 矩阵运算库(矩阵乘法、卷积底层)
libcufft.so # 快速傅里叶变换(你做频域处理用得上)
libcurand.so # GPU 随机数
libcusparse.so # 稀疏矩阵
它们的作用:当你 Python 里写 torch.matmul(a, b):
torch.matmul(a, b)
↓
PyTorch 的 C++ 代码调用 cuBLAS
↓
libcublas.so 里的函数把矩阵乘法翻译成 GPU 指令
↓
驱动 → GPU 执行
Runtime 就是这条链路上已经编译好的二进制库,它不编译新东西,只负责执行。
| 场景 | Runtime 出现吗? | 原因 |
|---|---|---|
| PyTorch 调用 cuBLAS | 不明显 | cuBLAS 内部已经封装 Runtime 调用 |
| 自定义 CUDA kernel (.so) | 必须 | kernel 调用 cudaMalloc/cudaMemcpy 等 Runtime API,需要加载 libcudart.so |
| 原理 | Runtime 提供 API 实现,把调用翻译给 Driver → GPU 执行 |
┌─────────────────────────────────────┐
│ 你的代码(Python / PyTorch) │ ← 你写的
├─────────────────────────────────────┤
│ PyTorch / TensorFlow / TensorRT │ ← 深度学习框架
├─────────────────────────────────────┤
│ cuDNN / cuBLAS / NCCL │ ← 库(算子、通信)
├─────────────────────────────────────┤
│ CUDA Runtime API(libcudart.so) │ ← cudaMalloc、cudaMemcpy 在这层
├─────────────────────────────────────┤
│ CUDA Driver API(libcuda.so) │ ← 更底层,cuMemAlloc、cuLaunchKernel
├─────────────────────────────────────┤
│ NVIDIA Kernel Driver(nvidia.ko) │ ← 内核态驱动,真正操作硬件
├─────────────────────────────────────┤
│ GPU 硬件 │ ← 物理芯片
└─────────────────────────────────────┘
⚪ DCN 算子是 自定义 CUDA kernel
-
你写的 C++ / CUDA 代码,通过
nvcc编译成dcn_kernel.so -
里面有 CUDA API 调用,比如:
-
cudaMalloc(分配 GPU 内存) -
cudaMemcpy(数据传输) -
cudaFree(释放 GPU 内存) -
甚至 kernel launch:
kernel<<<grid, block>>>()
-
这些 都是 CUDA Runtime API 调用的函数。
⚪为什么 PyTorch 自带 Runtime,但没有 nvcc
因为 PyTorch 已经替你编译好了。PyTorch 开发者在发布之前,就用他们自己的 nvcc 把所有核函数(卷积、矩阵乘法、BN 等)编译成二进制 .so,然后打包进 pip 包里。你装 PyTorch 相当于拿到了成品,不需要自己再编译,所以不需要 nvcc。
⚪nvcc 是什么
nvcc = NVIDIA CUDA Compiler(NVIDIA 的 CUDA 编译器)
它的作用是把 CUDA 源代码(.cu 文件)编译成 GPU 可执行的二进制。
⚪conda 和 Docker 有什么区别?什么时候用哪个?
- Conda 隔离 Python 生态(Python 版本、pip 包、PyTorch 自带的 Runtime)
- Docker 隔离整个操作系统层(nvcc、gcc、glibc、系统库)
- 纯训练/推理 → conda;自定义算子编译 / TensorRT 部署 / 多版本 CUDA 共存 → Docker
追问:能不能 Docker 里再套 conda?—— 可以,很多团队这么做,Docker 解决系统隔离,conda 管理 Python 依赖,分工清晰。
⚪PyTorch 装上之后为什么不需要系统装 CUDA Toolkit?
- PyTorch 的 wheel 包里预编译了 CUDA Runtime 和 cuDNN 二进制文件(在
torch/lib/下) - 系统只要有驱动,PyTorch 自带的 Runtime 就能调用 GPU
- 但 PyTorch 没带 nvcc,所以无法编译新的 CUDA 代码
⚪那 PyTorch 为啥要编译?
PyTorch 表面是 Python 库,但它内部真正干重活的部分用 C++ 和 CUDA 写的(Python 太慢,跑不动深度学习)。
拆开看 PyTorch 的代码仓库:
pytorch/
├── torch/ ← Python 代码(.py,不用编译)
├── aten/src/ ← C++ 代码(.cpp,必须编译)
├── aten/src/ATen/native/cuda/ ← CUDA 代码(.cu,必须用 nvcc 编译)
所以 PyTorch 的构建过程是:
-
用 gcc/g++ 把
.cpp编译成libtorch.so -
用 nvcc 把
.cu编译成libtorch_cuda.so -
Python 代码(
.py)打包,运行时加载前两步生成的.so库来调用 GPU
关键点:.so 文件就是 C++/CUDA 源码编译出来的二进制产物,是真正能让 CPU/GPU 执行的东西。
Wheel 和"编译"的关系
现在回到你上个问题的核心:
⚪如果没有 .whl,你 pip install torch 时会发生什么?
-
pip 下载 PyTorch 源码(
.tar.gz) -
在你的电脑上现场调用 gcc 编译所有
.cpp -
调用 nvcc 编译所有
.cu -
把编译出来的
.so放进site-packages/torch/lib/ -
这个过程通常 30 分钟到 2 小时,而且要求你机器装好 gcc + nvcc + 一堆系统库
有了 .whl 之后:
-
PyTorch 官方提前用他们的服务器一次性编译好
-
打包进
.whl里发到 PyPI -
你
pip install时只是下载 + 解压,不做任何编译 -
30 秒搞定,而且你机器不需要任何编译器
图示整个链路
源码(.c / .cpp / .cu) 人能看懂
↓ 编译器(gcc / nvcc)
机器码 / 二进制(.so / .exe) CPU/GPU 能执行
↓ 打包
.whl 包 pip 能装
↓ pip install
解压到 site-packages/ Python 能导入
↓ import torch
你的 Python 程序能调用 GPU ✅ 跑起来了
回到你的日常场景
你训练 ADF_UNet 时实际发生的事:
-
你写
model.py(Python 源码) -
python train.py,Python 解释器读你的代码 -
读到
import torch,加载 PyTorch 的.so二进制(官方预编译好的) -
你写
out = self.conv(x),PyTorch 内部的 C++ 代码调用 CUDA Runtime -
Runtime 把预编译好的卷积 kernel(也是
.so里的二进制)扔给 GPU 执行 -
GPU 跑完把结果返回
⚪整个链条上,"编译" 发生在 PyTorch 官方服务器上,不是你本地。你只是在使用编译好的成品。
PyTorch 官方在发布 wheel 包时,已经用 nvcc 把 CUDA kernel 编译成了 .so,你 pip install torch 只是下载成品。但如果你装 MMCV 的 DCN 算子,MMCV 的 .cu 源码没有预编译版本匹配你的环境,pip 就会在你本地现场调用 nvcc 编译,这时候你机器没 Toolkit(没 nvcc)就会报错
你的 Python 代码
↓
加载 dcn_kernel.so(nvcc 之前编译好的) ← 这里用 nvcc 的产物
↓
dcn_kernel.so 内部调用 cudaMalloc 等函数
↓
加载 libcudart.so(Runtime) ← 这里 Runtime 登场!Runtime 库(调用.so必须用Runtime)
↓
libcudart.so 把命令传给驱动
↓
GPU 执行
更多推荐


所有评论(0)