⚪正确的深度学习环境安装顺序

层级

内容

说明

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 版本有要求,优先服从这些依赖。

推荐的实际流程

  1. 装显卡驱动(Linux 服务器通常已经装好,nvidia-smi 能出结果就行)

  2. 装 Miniconda

  3. conda create -n myenv python=3.10 建环境

  4. 去 PyTorch 官网复制对应 CUDA 版本的安装命令,直接装

  5. 验证:python -c "import torch; print(torch.cuda.is_available())" 返回 True 就成了

两个 CUDA 相关命令的区别

命令

显示什么

nvidia-smi

驱动版本 + 驱动支持的最高 CUDA

nvcc -V

系统安装的 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 的构建过程是:

  1. gcc/g++.cpp 编译成 libtorch.so

  2. nvcc.cu 编译成 libtorch_cuda.so

  3. Python 代码(.py)打包,运行时加载前两步生成的 .so来调用 GPU

关键点:.so 文件就是 C++/CUDA 源码编译出来的二进制产物,是真正能让 CPU/GPU 执行的东西。

Wheel 和"编译"的关系

现在回到你上个问题的核心:

如果没有 .whl,你 pip install torch 时会发生什么?
  1. pip 下载 PyTorch 源码(.tar.gz)

  2. 你的电脑上现场调用 gcc 编译所有 .cpp

  3. 调用 nvcc 编译所有 .cu

  4. 把编译出来的 .so 放进 site-packages/torch/lib/

  5. 这个过程通常 30 分钟到 2 小时,而且要求你机器装好 gcc + nvcc + 一堆系统库

有了 .whl 之后:

  1. PyTorch 官方提前用他们的服务器一次性编译好

  2. 打包进 .whl 里发到 PyPI

  3. pip install 时只是下载 + 解压,不做任何编译

  4. 30 秒搞定,而且你机器不需要任何编译器

图示整个链路

源码(.c / .cpp / .cu)           人能看懂
       ↓ 编译器(gcc / nvcc)
机器码 / 二进制(.so / .exe)      CPU/GPU 能执行
       ↓ 打包
.whl 包                          pip 能装
       ↓ pip install
解压到 site-packages/            Python 能导入
       ↓ import torch
你的 Python 程序能调用 GPU       ✅ 跑起来了

回到你的日常场景

你训练 ADF_UNet 时实际发生的事:

  1. 你写 model.py(Python 源码)

  2. python train.py,Python 解释器读你的代码

  3. 读到 import torch,加载 PyTorch 的 .so 二进制(官方预编译好的)

  4. 你写 out = self.conv(x),PyTorch 内部的 C++ 代码调用 CUDA Runtime

  5. Runtime 把预编译好的卷积 kernel(也是 .so 里的二进制)扔给 GPU 执行

  6. 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 执行

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐