☰
Ubuntu 18.04下CUDA 11.8与vLLM安装路线及版本兼容实战
2026/11/5 6:15:27 网站建设 项目流程

Ubuntu 18.04 上装 CUDA 11.8,再往上叠一个 vLLM,这个组合我第一次接到需求时的反应是:机器是别人给的,动不了。老服务器跑着别的训练任务,驱动版本被卡死在一段不能随便升的区间里,而业务侧又希望同一台机器上多开一个推理服务。于是“Ubuntu 18.04 + CUDA 11.8 + vLLM 安装”这件事,就从一个简单的 pip 命令,变成了一个需要先把版本账算清楚、再决定走哪条路的工程问题。

这篇内容写给两类人:一类是手上握着不能重装系统的老机器、必须把 vLLM 跑起来的一线工程师;另一类是刚接触大模型推理部署、想搞清楚“为什么装个包会这么费劲”的同学。我会把三条安装路线(预编译包、源码编译、容器)的取舍讲透,把版本矩阵、编译参数、踩坑排查都摊开写,最后给一份能直接抄的清单。看完你应该能在自己那台 18.04 上,判断出“我这台机器到底该走哪条路”,而不是盲目复制一条 pip install 然后在报错里泡两天。

1. 先把版本账算清楚,别急着敲命令

1.1 三个组件的真实约束关系

很多人在这一步栽跟头,是因为把 CUDA Toolkit 和显卡驱动混为一谈。真正决定你能不能跑某个版本的,不是/usr/local/cuda-*这个目录,而是驱动版本。驱动是向上兼容的:装了 535 的驱动,底下的 11.8 和 12.1 运行时都能跑;但反过来,470 的驱动绝对跑不了 12.x 的运行时。所以“我要用 CUDA 11.8”这句话,本质上翻译过来是“我的驱动版本被限制在了 470 甚至更老,升不上去”。

那 vLLM 这边的约束又是什么?它不像 CUDA Toolkit 那样挑驱动,它挑的是 torch。vLLM 的每个发行版都死死绑住一个 torch 版本,torch 又绑住一个 CUDA 运行时版本。你在 PyPI 上装到的 vLLM 预编译包,从 0.5 版本之后基本是按 CUDA 12.1 编译的,内部链接的是libcudart.so.12。这意味着如果你的环境是纯 CUDA 11.8 且驱动卡在 470,直接pip install vllm之后大概率会看到ImportError: libcudart.so.12: cannot open shared object file,或者更隐蔽的 kernel 加载失败。

而 Ubuntu 18.04 这一层,加的是第三类麻烦:默认 Python 3.6、默认 gcc 7.5、默认 cmake 3.10,glibc 停在 2.27。vLLM 从 0.6 起要求 Python >= 3.9,编译链要求 cmake >= 3.26,这就注定了你不可能“什么都不改直接装”。

下面这张表是我整理的实际约束对照,建议动手前先对照自己机器填一遍:

组件Ubuntu 18.04 默认值vLLM 实际要求需要做的动作
Python3.6.9>= 3.9(0.6.x 起)源码编译 3.10 或用第三方 PPA
gcc / g++7.5建议 >= 8,且 <= 11装 gcc-9 并切换 alternatives
cmake3.10>= 3.26(编译期)pip 装 cmake wheel
glibc2.27大部分 wheel 要求 >= 2.17通常够用,个别包要求 2.28
驱动视机器而定CUDA 11.8 需 >= 450.80.02470 系列可用,525+ 更宽裕
内存视机器而定源码编译建议 >= 16G加 swap 或限 MAX_JOBS

1.2 驱动版本决定了你走哪条路

这是全文最重要的一句话:先看驱动,再谈方案。跑一条nvidia-smi看右上角的Driver Version,结论立刻分叉。

如果驱动是 525 及以上,你其实没必要死磕 11.8。直接装 CUDA 12.1 运行时对应的 torch,然后pip install vllm拿官方预编译包,十几分钟就能收工。11.8 只是这台机器历史上的选择,不是必须继承的负担——前提是这台机器上没有别的框架被钉在 11.8 上。

如果驱动是 470 到 520 之间,那 CUDA 11.8 是你能用的上限,这条路必须走,而且 vLLM 基本只能源码编译。因为官方预编译包是按 12.1 构建的,你硬装下去,pip 会把nvidia-cuda-runtime-cu12这一串包一起拽进来,运行时可能出现“torch 是 cu118、vLLM 的 kernel 是 cu12 编译”的混合状态,症状是能 import、能建模、一跑推理就崩,排查起来极其痛苦。

如果驱动更老(比如 450 刚够线),那 11.8 是硬约束,同时建议直接放弃在这台机器上跑大模型推理,先评估换卡或换机的成本——很多新模型的算子在这些卡上根本没有可用的 kernel。

1.3 三条路线怎么选

我把三条路线的适用条件列成表,你可以直接对号入座:

路线适用场景耗时风险点
预编译 wheel驱动 >= 525,或不介意装 cu121 运行时10-20 分钟与现有 cu118 环境冲突
源码编译驱动锁死 11.8、必须纯 cu11840-90 分钟编译期 OOM、cmake 版本、toolkit 路径
容器镜像机器能装 container runtime、允许隔离20-30 分钟驱动兼容性、共享内存、模型挂载

我个人在受控环境里最推荐容器,理由很简单:它把 Python、gcc、cmake、CUDA 运行时全部打包,宿主机的 18.04 只需要提供一个足够新的驱动。你不需要为一个推理服务去污染宿主机上跑着的训练环境。但如果机器上连 container runtime 都没装、或者运维不允许,那就老老实实走源码编译,这也是本文的重点。

2. 动手前的地基工程:Python、编译器和驱动

2.1 五条命令摸清家底

别急着装东西。老机器最大的风险是你以为它是干净的,其实早就被前任装过三套 CUDA、两套 conda。先跑这几条:

nvidia-smi # 驱动版本、显卡型号、显存 nvcc --version 2>/dev/null # 有没有 toolkit,什么版本 ls -l /usr/local/ | grep cuda # 有几套 CUDA 并存 python3 --version && which python3 # 默认 Python gcc --version && cmake --version # 编译链版本 free -h && df -h / # 内存和磁盘

重点看三件事。第一,nvidia-smi里的显卡型号,它决定了后面TORCH_CUDA_ARCH_LIST怎么填,填错了编译出来的 kernel 在你卡上跑不了。第二,/usr/local下如果有多个 cuda 目录,后面的环境变量必须以你指定的那套为准,不能让 PATH 里的顺序随机决定。第三,free -h里的可用内存,编译 vLLM 的 CUDA 扩展时峰值很容易吃到 12G 以上,内存不够就得靠 swap 或者把并发降下来。

还有一条容易被忽略的检查:/dev/shm的大小。跑张量并行或者大 batch 推理时,进程间通信会用到共享内存,很多容器默认只给 64M,会直接报错。用df -h /dev/shm看一眼,小于 1G 的都要调整。

2.2 Python 3.10 为什么是这里的最优解

vLLM 0.6.x 要求 Python >= 3.9。理论上 3.9、3.10、3.11 都行,但在这台 18.04 上,3.10 是最稳的那个点。

原因在 OpenSSL。Ubuntu 18.04 仓库里的libssl-dev是 1.1.1 系列,你用它编 Python 3.10 完全没问题;但从 3.12 开始,CPython 对 OpenSSL 版本的要求抬高了,configure 阶段就容易报错,你得先自己编一套新版 OpenSSL 再来编 Python,工作量翻倍。而 3.9 又偏老,有些新版本的依赖包已经不再提供 3.9 的 wheel,会逼你去本地编译。3.10 正好在“依赖包都还支持”和“系统库够用”的交叉点上。

编译安装的完整步骤:

sudo apt update sudo apt install -y build-essential zlib1g-dev libncurses5-dev \ libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev \ libsqlite3-dev libbz2-dev liblzma-dev uuid-dev tk-dev cd /tmp curl -O https://www.python.org/ftp/python/3.10.13/Python-3.10.13.tgz tar -xf Python-3.10.13.tgz && cd Python-3.10.13 ./configure --prefix=/usr/local --with-ensurepip=install make -j$(nproc) sudo make altinstall

几个细节值得说。--enable-optimizations会启用 PGO,编译时间从 3 分钟变成 15 分钟以上,小内存机器还可能中途 OOM,我一般不开——为了那 5% 的启动性能提升,不值。用altinstall而不是install,是为了不覆盖系统的python3,18.04 上有一堆系统工具依赖 3.6,覆盖了会出问题。--enable-shared我一般也不加,加了之后每次运行都要配LD_LIBRARY_PATH,纯属给自己找麻烦。

装完验证python3.10 -V,然后建虚拟环境时统一用绝对路径,避免 PATH 混乱:

/usr/local/bin/python3.10 -m venv /opt/venvs/vllm source /opt/venvs/vllm/bin/activate pip install --upgrade pip setuptools wheel

2.3 驱动和 CUDA 11.8 的正确装法

如果驱动已经在新版本区间,别动它。装驱动这件事的风险远大于收益,尤其是在有别的服务在跑的机器上。你只需要装 CUDA Toolkit。

用 runfile 方式装,安装过程中务必取消勾选 Driver 那一项。这一步是关键,很多人手一抖把驱动一起装了,结果装进去一个比现有版本更老的驱动,重启后nvidia-smi直接报 mismatch,整台机器起不来。

sudo sh cuda_11.8.0_520.61.05_linux.run --toolkit --silent --override

--toolkit只装工具链,--silent免交互,--override跳过编译器版本检查(18.04 的 gcc 7.5 会触发警告,但实际能编)。

装完在/etc/profile.d/下加一个脚本,把路径固定住:

export CUDA_HOME=/usr/local/cuda-11.8 export PATH=$CUDA_HOME/bin:$PATH export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH

这里有个容易踩的坑:/usr/local/cuda这个软链接可能指向别的版本。永远用带版本号的绝对路径,不要图省事用cuda。我见过一台机器上软链接指到了 10.2,编译时 nvcc 版本和 torch 版本对不上,报错信息完全误导人。

至于驱动本身,如果确实需要升级,流程是:先apt purge掉所有旧的驱动相关包,把 nouveau 加入黑名单,重启进文本模式,再装新驱动,重启验证。这套操作在老机器上一次成功率大概七成,剩下的三成里有一半是内核头文件缺失导致的 DKMS 编译失败。所以我的建议是:能不升就不升,先确认你现在的驱动到底能不能撑住你的目标方案。

2.4 编译工具链:gcc、cmake、ninja 一个都不能少

CUDA 11.8 支持的 gcc 上限是 11,Ubuntu 18.04 默认的 7.5 虽然勉强能编,但 vLLM 里大量使用 C++17 特性,gcc 7 对其中一部分支持不完整,容易在编译中后期报一堆模板错误。装 gcc-9,然后用 alternatives 切过去:

sudo apt install -y gcc-9 g++-9 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 90

cmake 是另一个硬门槛。18.04 自带 3.10,而 vLLM 的构建脚本要求 3.26 以上。最省事的办法是用 pip 装一个,它自带预编译二进制,不依赖系统 glibc 太新的版本:

pip install "cmake>=3.26" ninja

装完之后which cmake应该指向虚拟环境里的那个。如果你的虚拟环境外面还有别的构建流程要用 cmake,注意不要让这个 pip 版本的 cmake 污染全局环境。

最后是内存。编译 vLLM 的 CUDA kernel 时,nvcc 对每个源文件都要吃掉 2-4G 内存,并发数一高就 OOM。如果机器内存只有 16G,加上 swap:

sudo fallocate -l 16G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile && sudo swapon /swapfile

swap 会让编译变慢,但总比编译到 80% 被杀掉强。用MAX_JOBS=4控制并发,效果比堆 swap 更好。

3. 路线 A:源码编译 vLLM 的完整实操

3.1 版本组合怎么定,先让 pip 告诉你

选版本这一步,不要凭记忆。我见过太多人照着半年前的博客装vllm==0.4.2,结果发现那个版本不支持他现在要跑的模型。

最可靠的方法是让 pip 自己算。用--dry-run让 pip 只解析依赖不实际安装:

pip install "vllm==0.6.1" --dry-run 2>&1 | head -40

输出里会明确列出它打算装的 torch 版本。你拿这个 torch 版本去 PyTorch 的 wheel 索引页面确认有没有 cu118 的构建,如果有,说明这个 vLLM 版本在你的环境里是有解的;如果没有,就往下降一个 vLLM 版本再试。

我实测下来,在 CUDA 11.8 环境下比较稳的组合是 vLLM 0.6.x 配 torch 2.4/2.5 的 cu118 构建。但这不是金科玉律,因为你还要考虑模型支持度——太老的 vLLM 不认识新模型的架构,加载时会报architecture is not supported。

版本定下来之后,先把 torch 单独装好,验证它能识别到显卡,再装 vLLM:

pip install torch==2.4.0 torchvision==0.19.0 \ --index-url https://download.pytorch.org/whl/cu118 python -c "import torch; print(torch.__version__, torch.version.cuda, torch.cuda.is_available())"

期望输出是2.4.0 11.8 True。如果cuda.is_available()是 False,别往下走了,先解决这个,通常是驱动版本不够或者 CUDA_VISIBLE_DEVICES 被设置成了空值。

3.2 拉源码、装依赖、控环境变量

源码编译的核心是“关掉构建隔离”。pip 默认会给每个包创建独立的构建环境,这意味着它会在一个干净的沙箱里重新下载 torch,然后编译 vLLM 的扩展。这个 torch 很可能不是你刚装的那个版本,甚至可能是 CPU 版本,编译出来的东西当然没法用。

git clone https://github.com/vllm-project/vllm.git cd vllm git checkout v0.6.1 git submodule update --init --recursive pip install -r requirements-build.txt pip install -r requirements-cuda.txt

requirements-cuda.txt里包含了编译所需的一切,包括 xformers、flash-attn 之类的加速库。这一步如果在国内网络环境下很慢,可以给 pip 配上你所在网络里响应最快的镜像源。

然后是环境变量,这几行决定了编译能不能成功:

export CUDA_HOME=/usr/local/cuda-11.8 export PATH=$CUDA_HOME/bin:$PATH export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH export TORCH_CUDA_ARCH_LIST="7.0;7.5;8.0;8.6" export MAX_JOBS=4 export NVCC_THREADS=2

TORCH_CUDA_ARCH_LIST需要重点解释。它告诉 nvcc 只针对这些计算能力编译 kernel。填得越多,编译越慢、产物体积越大;填得越少,编译快,但换一张卡就不能用了。常见对应关系如下:

显卡系列计算能力备注
V1007.0不支持 bf16,只能用 fp16
T47.5显存小,适合小模型
A1008.0支持 bf16
A10 / A6000 / 30908.6主流推理卡
4090 / L408.9支持 fp8 的新架构
H1009.0需要更新的 toolkit

只填你机器上实际有的那张卡的能力值。如果你只在一台 T4 机器上跑,就填"7.5",编译时间能从 50 分钟降到 20 分钟。

3.3 开始编译,以及中途出错怎么办

pip install -e . --no-build-isolation -v 2>&1 | tee build.log

--no-build-isolation是灵魂参数,它让 pip 用当前环境里的 torch 去编译,而不是另起炉灶。-v输出详细日志,配合tee把日志留下来,出错时方便定位。

编译过程分三段:先编 C++ 部分(大约 3-5 分钟),然后_C这个 CUDA 扩展(最慢,占 80% 的时间),最后编各种自定义 kernel。中间会看到大量的warning,这些基本都可以忽略,真正致命的是error。

如果编译在 CUDA 那一段被杀掉,日志里出现Killed或者cc1plus: out of memory,那是内存不够,把MAX_JOBS降到 2,确保 swap 已经挂上,重来。

如果报fatal error: cuda_runtime.h: No such file or directory,说明CUDA_HOME没生效,检查echo $CUDA_HOME和ls $CUDA_HOME/include/cuda_runtime.h。

如果报 gcc 版本相关的错误,比如error: unrecognized command line option '-std=c++17',说明 alternatives 没生效,gcc --version确认一下是不是 9。

3.4 编译产物校验:别等上线才发现白编了

编译成功不等于能用。装完之后立刻做三层验证,一层比一层深。

第一层,检查扩展能不能加载:

python -c "import vllm; print(vllm.__version__)" python -c "from vllm import _C; print('ext ok')"

第二层,检查 kernel 是否匹配你的卡。用一个小模型跑一次真实推理,别用 mock:

python - <<'EOF' from vllm import LLM, SamplingParams llm = LLM(model="/data/models/Qwen2.5-0.5B-Instruct", dtype="half", max_model_len=2048) out = llm.generate(["你好,介绍一下你自己"], SamplingParams(max_tokens=64)) print(out[0].outputs[0].text) EOF

如果这一步报no kernel image is available for execution on the device,就是TORCH_CUDA_ARCH_LIST填错了,或者编译时用的 torch 是 CPU 版本。回去查build.log里 nvcc 的-gencode参数,能看到实际编了哪些架构。

第三层,测吞吐。用vllm bench或者简单写个循环发请求,看每秒能出多少 token。这一步的意义是发现“能跑但极慢”的情况,通常原因是没编进来 flash-attn,退化到了朴素实现。

3.5 起服务时的几个关键参数

推理服务化用 OpenAI 兼容接口最省事:

python -m vllm.entrypoints.openai.api_server \ --model /data/models/Qwen2.5-7B-Instruct \ --served-model-name qwen-7b \ --host 0.0.0.0 --port 8000 \ --dtype half \ --max-model-len 8192 \ --gpu-memory-utilization 0.90 \ --swap-space 8 \ --disable-log-requests

--dtype half在 V100 和 T4 上是必须的,这两代卡不支持 bf16,用auto会让 vLLM 尝试 bf16 然后报错或者退化成 fp32 撑爆显存。--gpu-memory-utilization 0.90是预分配的显存比例,vLLM 会一口气吃掉这部分做 KV cache,所以要留 10% 给 CUDA context 和临时张量。--swap-space是 CPU 侧的交换空间,遇到长请求排队时有用,但要保证/dev/shm足够大。

还有一个参数--enforce-eager,它会关掉 CUDA Graph 捕获。代价是吞吐降低 10%-20%,好处是启动快、显存占用低、不容易因为图捕获失败而卡死。在调试阶段我一般开着它,等一切稳定了再去掉。

4. 路线 B:预编译包的快速通道

4.1 什么情况下可以偷懒

如果你的驱动够新(525+),其实有个更省事的做法:别管机器上装的是 CUDA 11.8,直接装 cu121 的 torch 加官方 vLLM wheel。驱动向上兼容,11.8 的 toolkit 装着不影响你跑 12.1 的运行时,因为 pip 的nvidia-cuda-runtime-cu12这些包自带运行时库。

pip install torch==2.5.1 --index-url https://download.pytorch.org/whl/cu121 pip install vllm==0.6.3

整个过程十分钟内搞定,不用编译,不用管 cmake 版本,不用管 gcc。这是我最推荐大多数人的路径。

但有个前提必须确认:nvidia-smi能正常输出,且驱动版本 >= 525。低于这个数,cu121 的运行时初始化会失败。

4.2 混合环境的清理

老机器上最大的隐患是“装过一版又装一版”。cu118 和 cu121 的运行时库同时存在于 site-packages 里,谁先被加载取决于文件系统顺序,结果就是玄学崩溃。

清理的办法很简单:重建虚拟环境。别在旧环境上修修补补,pip uninstall的残留文件会一直在那儿。规程是:删掉/opt/venvs/vllm,重新python3.10 -m venv,重新装。养成这个习惯能省掉大量莫名其妙的排查时间。

验证环境是否干净,用这条:

pip list | grep -iE "torch|nvidia|vllm"

看输出里是不是只有一套 cu12 相关的包,有没有nvidia-cuda-runtime-cu11和cu12同时存在的现象。

5. 踩坑速查表:报错、原因、处置

5.1 动态库和符号类问题

这类问题占了我在老系统上遇到的一半以上,症状是“装完了、import 就炸”。

报错关键字真实原因处置方式
libcudart.so.12: cannot opentorch 是 cu118,vLLM 要 cu12统一版本,或源码编译
libcudart.so.11.0: cannot open没装 cu118 运行时或路径没配装 torch cu118 或设 LD_LIBRARY_PATH
undefined symbol: _ZN2at...torch 与 vLLM 版本不匹配按 dry-run 结果重装
version GLIBC_2.28 not found某个 wheel 编译时用了更新的 glibcobjdump -T x.so | grep GLIBC_定位后降版本
libgomp.so.1: cannot opengcc 运行时缺失apt install libgomp1

排查GLIBC这类问题有个好用的命令:ldd看依赖树,objdump -T看某个 so 要求的符号版本。找到具体是哪个文件要求的 2.28,再决定是降那个包的版本,还是放弃。

5.2 显存和性能类问题

torch.cuda.OutOfMemoryError不一定真的是显存不够。可能是--max-model-len设得太大,vLLM 按最坏情况预留 KV cache,直接把显存吃满。也可能是--gpu-memory-utilization设成了 0.95,连 CUDA context 的空间都没留。

诊断顺序是:先降--gpu-memory-utilization到 0.85,再降--max-model-len,最后考虑降--max-num-seqs。如果这些都不行,那就是模型本身在你卡上放不下,得换量化版本或者换卡。

另一个常见现象是“能跑但很慢”。先看启动日志里有没有Using FlashAttention backend这类信息,如果退化到了xformers或者朴素实现,吞吐会差一大截。老卡上 flash-attn 的预编译包往往没有对应版本,这里要么接受性能损失,要么自己编 flash-attn(很折腾)。

5.3 环境和启动类问题

服务起不来但没报错,通常是端口被占或者 host 绑定错了。--host 0.0.0.0才能被外部访问,默认的127.0.0.1只能本机连。

进程被 OOM Killer 干掉,看一下dmesg | tail -20有没有Out of memory: Killed process。这种情况一般是模型加载阶段内存峰值太高,解法是加 swap 或者用--load-format分片加载。

还有一个隐蔽的坑:/dev/shm太小。报错信息通常是Bus error或者 NCCL 初始化失败。用df -h /dev/shm查,容器里需要启动时加--shm-size=8g。

6. 我踩过之后总结的几条经验

版本一旦跑通,第一件事是把pip freeze > requirements.lock存下来。这台机器上的组合是花了几个小时试出来的,下次重装或者扩容,照着锁文件走,别再重新试一遍。锁文件里要包含 torch、vllm、xformers、transformers 这几个关键包的确切版本,缺一个都可能复现不了。

第二,别在生产机器上编译。编译过程会吃掉大量 CPU 和内存,如果这台机器同时还跑着训练任务,很容易互相影响。我的做法是在一台配置相同的测试机上编好,把pip freeze的结果和一个完整的虚拟环境目录打包过去,用--no-index离线安装。

第三,对于这种“系统版本老、组件要求新”的场景,长期看容器是唯一可持续的方案。宿主机的 18.04 只要提供一个足够新的驱动,剩下的全部隔离在镜像里。你不需要为了一个推理服务去动一台跑着关键任务的机器,也不用担心某次apt upgrade把 gcc 换掉导致环境失效。

最后一个实战心得:如果编译反复失败且时间成本已经超过半天,果断换容器方案。我见过太多人在源码编译上耗掉两天,最后发现容器镜像里已经把一切调好了。判断标准很简单——编译失败超过三次,且每次都是不同原因,说明这套环境的坑比你预想的多,继续投入的边际收益已经很低了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询