## 问题场景
conda 环境里装了 CUDA Toolkit,但 `nvcc`、cuBLAS 头文件或运行时库仍然指向系统的旧版本(通常是 `/usr/local/cuda/`),导致编译或运行时版本不匹配。
## 前置诊断
先确认你的 CUDA 是怎么装的:
# 1. 系统 CUDA 版本
bash
/usr/local/cuda/bin/nvcc --version
# 2. conda 环境中的 CUDA
bash
conda list -n VLLM | grep cuda
pip list | grep -iE "cuda|nvidia-cuda"
# 3. 当前 PATH 实际用的是哪个
bash
which nvcc
然后对照下面场景操作。
conda 在激活环境时会自动将 $CONDA_PREFIX/bin 加入 PATH 最前面,这样 nvcc 就会优先使用 conda 内的版本。
但头文件和库文件的搜索路径需要额外处理,好在 conda 的 cudatoolkit 包通常会自动设置以下环境变量(通过 etc/conda/activate.d/ 脚本),你可以检查是否存在:
bash
ls $CONDA_PREFIX/etc/conda/activate.d/
## 场景一:CUDA 通过 pip 安装
**判断依据**:
bash
pip list | grep nvidia-cuda
`有输出,如 `nvidia-cuda-nvcc`、`nvidia-cuda-runtime` 等。
**路径特征**:
所有 CUDA 文件在 site-packages下:
```
$CONDA_PREFIX/lib/python3.12/site-packages/nvidia/cu13/
├── bin/ # nvcc, fatbinary, nvlink, ptxas
├── include/ # CUDA 头文件
└── lib/ # libcudart.so 等运行时库```
### 配置步骤
# 1. 清理可能的旧配置
bash
# 打开终端,先删除可能存在的旧设置(仅当前会话):
unset CPLUS_INCLUDE_PATH
unset C_INCLUDE_PATH
unset LD_LIBRARY_PATH
# 如果你把它们写入了激活脚本,也请编辑删除:
rm -f $CONDA_PREFIX/etc/conda/activate.d/env_vars.sh
# 2. 设置 CUDA 主路径变量(这里以 cu13 为例,请根据实际情况修改目录名)
bash
CUDA_PIP_ROOT="${CONDA_PREFIX}/lib/python3.12/site-packages/nvidia/cu13"
# 3. 创建激活脚本
bash
mkdir -p $CONDA_PREFIX/etc/conda/activate.d
cat << EOF > $CONDA_PREFIX/etc/conda/activate.d/cuda_env.sh
#!/bin/sh
# pip 安装的 CUDA Toolkit 路径
CUDA_ROOT="${CONDA_PREFIX}/lib/python3.12/site-packages/nvidia/cu13"
export CUDA_HOME="\${CUDA_ROOT}"
export PATH="\${CUDA_ROOT}/bin:\${PATH}"
# 编译头文件路径
export C_INCLUDE_PATH="\${CUDA_ROOT}/include:\${C_INCLUDE_PATH}"
export CPLUS_INCLUDE_PATH="\${CUDA_ROOT}/include:\${CPLUS_INCLUDE_PATH}"
# 编译时链接路径
export LIBRARY_PATH="\${CUDA_ROOT}/lib:\${LIBRARY_PATH}"
# 运行时库路径
export LD_LIBRARY_PATH="\${CUDA_ROOT}/lib:\${LD_LIBRARY_PATH}"
EOF
# 4. 创建停用脚本
bash
mkdir -p $CONDA_PREFIX/etc/conda/deactivate.d
cat << EOF > $CONDA_PREFIX/etc/conda/deactivate.d/cuda_env.sh
#!/bin/sh
unset CUDA_HOME
unset C_INCLUDE_PATH
unset CPLUS_INCLUDE_PATH
unset LIBRARY_PATH
unset LD_LIBRARY_PATH
EOF
## 场景二:CUDA 通过 conda 安装
**判断依据**:`
bash
conda list | grep cudatoolkit
conda list | grep cuda-toolkit
**路径特征**:
文件和标准的 Linux 目录布局一致:
```
$CONDA_PREFIX/
├── bin/ # nvcc
├── include/ # CUDA 头文件
└── lib/ # libcudart.so 等
```
### 配置步骤
# 1. 清理旧配置
bash
# 打开终端,先删除可能存在的旧设置(仅当前会话):
unset CPLUS_INCLUDE_PATH
unset C_INCLUDE_PATH
unset LD_LIBRARY_PATH
# 如果你把它们写入了激活脚本,也请编辑删除:
rm -f $CONDA_PREFIX/etc/conda/activate.d/env_vars.sh
# 2. 创建激活脚本
bash
mkdir -p $CONDA_PREFIX/etc/conda/activate.d
cat << 'EOF' > $CONDA_PREFIX/etc/conda/activate.d/cuda_env.sh
#!/bin/sh
export CUDA_HOME="${CONDA_PREFIX}"
# conda 默认会把 $CONDA_PREFIX/bin 加入 PATH,这里确保优先级
export PATH="${CONDA_PREFIX}/bin:${PATH}"
# 编译头文件路径
export C_INCLUDE_PATH="${CONDA_PREFIX}/include:${C_INCLUDE_PATH}"
export CPLUS_INCLUDE_PATH="${CONDA_PREFIX}/include:${CPLUS_INCLUDE_PATH}"
# 编译时链接路径
export LIBRARY_PATH="${CONDA_PREFIX}/lib:${CONDA_PREFIX}/lib/stubs:${LIBRARY_PATH}"
# 运行时库路径
export LD_LIBRARY_PATH="${CONDA_PREFIX}/lib:${CONDA_PREFIX}/lib/stubs:${LD_LIBRARY_PATH}"
EOF
# 3. 创建停用脚本
bash
mkdir -p $CONDA_PREFIX/etc/conda/deactivate.d
cat << 'EOF' > $CONDA_PREFIX/etc/conda/deactivate.d/cuda_env.sh
#!/bin/sh
unset CUDA_HOME
unset C_INCLUDE_PATH
unset CPLUS_INCLUDE_PATH
unset LIBRARY_PATH
unset LD_LIBRARY_PATH
EOF
## 场景三:pip 和 conda 混合安装
如果 `nvidia-cuda-nvcc `(pip 装)和 `cuda-command-line-tools `(conda 装)混在一起,很容易冲突。建议:
只保留一种,卸载另一种
bash
pip uninstall nvidia-cuda-nvcc nvidia-cuda-runtime nvidia-cuda-cupti -y # 卸载 pip 版
conda install -c nvidia cuda-toolkit # 用 conda 版
然后按场景二配置
或者反过来,全部用 pip:
bash
conda remove --force cudatoolkit # 卸载 conda 版
然后按场景一配置
## 生效与验证
# 1. 重新激活环境
bash
conda deactivate
conda activate env # 换成你的环境名
# 2. 逐项验证
bash
which nvcc # 必须是 conda 环境的路径
nvcc --version # 必须是期望的 CUDA 版本
echo $CUDA_HOME # 必须非空且指向 conda 环境
echo $LD_LIBRARY_PATH # conda 路径应排在 /usr/local/cuda 前面
# 3. 如果 which nvcc 还是系统路径
# 说明 PATH 被 shell 配置文件(.bashrc 等)污染了,检查并清理:
bash
grep -n 'cuda' ~/.bashrc
grep -n 'cuda' ~/.profile
## 特别注意:flashinfer 及其他 JIT 编译库
flashinfer、xformers 等库会在**运行时** JIT 编译 CUDA kernel,依赖 `nvcc` 和 CUDA 头文件,并在 `~/.cache/` 下缓存编译产物。
切换 CUDA 版本后,**必须清除旧缓存**,否则会使用旧版本编译出的 .so 文件导致版本不匹配:
# 清除所有可能受影响的缓存
bash
rm -rf ~/.cache/flashinfer
rm -rf ~/.cache/torch_extensions
## 快速参考:关键环境变量
| 变量 | 作用 | 被谁使用 |
|------|------|----------|
| `CUDA_HOME` | CUDA 安装根目录 | nvcc、CMake、PyTorch 扩展编译 |
| `PATH`(含 `bin/`) | 查找 `nvcc` 可执行文件 | flashinfer JIT、任何调用 nvcc 的构建 |
| `C_INCLUDE_PATH` / `CPLUS_INCLUDE_PATH` | C/C++ 头文件搜索路径 | gcc/nvcc 编译 CUDA 扩展 |
| `LIBRARY_PATH` | 编译时链接库搜索路径 | 链接器 ld |
| `LD_LIBRARY_PATH` | 运行时动态库搜索路径 | 动态链接器,加载 .so 文件 |
## 补充说明:
| 来源 | 包名 | 现状说明 |
|---|---|---|
| conda | cudatoolkit | 旧名,已弃用,现推荐使用 conda-forge 源的 cuda-toolkit |
| conda-forge | cuda-toolkit | Conda 环境下安装 CUDA 的官方推荐方案 |
| pip | cuda-toolkit | 仅为空壳元包,无实际文件,核心组件拆分至多个独立分包 |
| pip | nvidia-cuda-nvcc、nvidia-cuda-runtime、nvidia-cuda-cccl 等 | Pip 渠道存放 CUDA 完整运行、编译组件的实际分包 |