上个月帮某团队在一台 Linux 服务器上部署开源大模型,按着网上的教程一条条执行,结果一个下午全耗在奇怪的问题上——不是模型文件下载不下来,就是容器里调用不到 GPU,好不容易把服务跑起来了,并发一上去立刻报显存溢出。这类场景我见过太多次,原因不在于命令本身难,而在于Linux服务器部署大模型这个事,核心从来不是“跑通一条命令”,而是“让模型在给定硬件上长期稳定地提供服务”。本文把我实际部署开源大模型的经验完整梳理一遍,从环境准备、框架选型、显存估算到性能调优,再到一连串容易踩的坑,希望能给正准备在自己服务器上部署大模型的读者一些可以照做的参考。
需要说明的是,模型部署没有唯一标准答案,同样的模型在不同的GPU、不同的推理框架、不同的并发需求下,最优方案可能完全不同。所以这篇内容不只给结论,更会解释每个关键选择的理由,方便你根据自己的服务器配置做判断。
1. 部署前先想清楚:模型多大、谁来推理、显存够不够
很多人一上来就急着找部署教程,结果环境的坑还没踩完,模型已经换了好几个。我自己的经验是,部署前先花半小时回答三个问题,后面能少走三天弯路。
1.1 一句话估算模型需要多少显存
大模型显存消耗主要来自三块:模型权重、KV Cache、中间激活值。其中权重是大头,也是最好估算的。
模型权重占用有个简单的计算公式:参数量乘以每个参数占用的字节数。
- FP32(4字节):大多数情况下没必要用,精度高但显存开销太大;
- FP16/BF16(2字节):主流部署精度,质量和显存平衡最好;
- INT8(1字节):权重压缩为8位,显存直接减半;
- INT4(0.5字节左右):权重压缩为4位,显存进一步下降,但推理质量会有轻微损失。
以常见规格举例:
| 模型规模 | 参数总量 | FP16权重显存 | INT4量化后权重显存 | 实际部署建议显存 |
|---|---|---|---|---|
| 7B级 | 约70亿参数 | 约14GB | 约4GB | 单卡24GB起步 |
| 13B级 | 约130亿参数 | 约26GB | 约7GB | 单卡24GB或双卡 |
| 70B级 | 约700亿参数 | 约140GB | 约35GB | 多卡80GB×2或更多 |
但注意,权重显存只是底线。模型推理过程中还要给KV Cache和激活值留空间,这部分和并发数、上下文长度强相关。经验法则是:按权重显存的1.3到1.5倍预留总显存,并发高或上下文长的场景还要继续往上加。
1.2 推理框架怎么选
部署大模型时,很多人默认用某个框架直接硬扛,但不同框架的侧重点差别很大。
| 方案 | 启动复杂度 | 适合场景 | 并发能力 | 备注 |
|---|---|---|---|---|
| 直接加载权重推理 | 低 | 测试、单次问答 | 很弱 | 适合快速验证效果 |
| Ollama | 极低 | 内网个人使用、日常调试 | 一般 | 封装完善,省心 |
| vLLM | 中等 | 线上API服务、高并发 | 强 | 工业级首选 |
| 各种本地推理工具 | 低 | 个人电脑、临时演示 | 弱 | 依赖环境 |
我个人的选型逻辑很简单:如果只是想自己在内网用一用,Ollama 足够;如果要给业务系统提供 API 接口,或者团队多人同时访问,直接上 vLLM。后面会分别讲这两种方案的完整部署过程。
1.3 单卡、多卡还是CPU兜底
显存够用就单卡跑,这是最省事的方式。显存不够时,优先考虑量化降低权重占用,其次考虑多卡并行。多卡并行不是简单的“把模型拆开往两张卡上一丢”就行,它涉及张量并行、流水线并行等机制,依赖 GPU 之间的高速通信,如果服务器主板不支持良好的卡间通信,多卡效率会非常难看。至于 CPU 部署,能做但速度慢得多,只适合没有 GPU 或模型规模极小的兜底场景。
2. Linux服务器基础环境:驱动、CUDA、容器一步到位
环境准备是部署大模型的第一道坎,也是最容易翻车的地方。整个链路里,驱动、CUDA、PyTorch 三者必须互相匹配,版本差一个都可能让人折腾到怀疑人生。
2.1 裸装依赖链 vs 容器化方案
裸装需要手动装显卡驱动、CUDA 工具包、cuDNN,再装 Python 环境、PyTorch 等,版本稍有不对,轻则警告,重则完全用不了 GPU。我见过不少人在服务器上反复卸载重装驱动,最后发现是 CUDA 版本和 PyTorch 编译版本不匹配。
我的建议很直接:能用容器就不要裸装。Docker 容器本身不解决驱动问题,但可以把 CUDA、PyTorch、依赖库全部固化在镜像里,宿主机只需要提供显卡驱动。这样换环境、重建服务都方便很多。
2.2 配置容器GPU支持
宿主机上需要先装好显卡驱动,然后用nvidia-container-toolkit让 Docker 容器能访问 GPU。大致流程如下:
# 安装NVIDIA Container Toolkit(以Debian系为例) apt-get update apt-get install -y nvidia-container-toolkit # 重启Docker服务使配置生效 systemctl restart docker装完后验证一下容器能否识别 GPU:
docker run --rm --gpus all <镜像名> nvidia-smi能正常输出显卡信息就说明容器访问 GPU 的通道打通了。这一步如果做不好,后面所有部署都没法进行。
2.3 拉取合适的运行镜像
为了省去手动安装 CUDA 和 PyTorch 的麻烦,可以直接拉取包含 CUDA 和 PyTorch 的基础镜像。选镜像时有一件事要注意:镜像里的CUDA版本最好和宿主机驱动的兼容性保持一致。判断方法很简单,宿主机上用nvidia-smi查看驱动支持的 CUDA 版本,然后选择镜像内部的 CUDA 版本不超过驱动支持的上限即可。
拉取镜像并启动容器时,建议把模型目录和代码目录都挂载进去,方便后续更新模型:
docker run -d --name llm-server \ --gpus all \ -p 8000:8000 \ -v /data/models:/models \ -v /data/app:/app \ <镜像名> tail -f /dev/null进入容器后先用 Python 验证一下 PyTorch 能否正常调用 GPU:
docker exec -it llm-server bash python -c "import torch; print(torch.cuda.is_available()); print(torch.cuda.device_count())"如果返回True,说明环境已经通了。这一步验证环境比任何复杂配置都有意义,它能帮你把“环境问题”和“代码问题”快速分开。
3. 高性能推理部署:vLLM与量产级API服务
vLLM 是我在线上环境使用最多的推理框架。它的优势在于高吞吐和稳定的并发能力,下面说说它为什么快,以及怎么快速部署出一个可用的API服务。
3.1 vLLM快在什么地方
vLLM 的核心优化有两点:
第一是PagedAttention(分页注意力),它把 KV Cache 按页管理,显存利用率大幅提升。传统推理框架一般会为最大可能的序列长度预留连续的 KV Cache,但这些内存未必被完全用到;分页机制则按需分配,显存浪费少了很多。
第二是Continuous Batching(连续批处理),传统批处理要等一批请求全部完成才开始下一批,导致 GPU 在请求陆续到达时利用率不高;vLLM 会在每一步动态调整批内的请求集合,请求完成的就走,新来的请求可以立即补上,吞吐量因此成倍提升。
从部署角度说,这些优化意味着同样的硬件,vLLM 能支撑更高的并发,这正是线上服务需要的。
3.2 模型文件下载与目录规划
模型文件通常几百兆到几十GB不等,下载前要规划好存储位置。我自己习惯把模型单独放在/data/models目录下,每个模型一个子目录,按“模型名-参数规模-精度格式”命名,例如:
/data/models └── qwen-7b-chat-fp16 ├── config.json ├── model-00001-of-0000X.safetensors └── tokenizer.json这样即使用多个模型切换,也不容易混淆。下载模型时优先从国内可访问的模型托管平台或配置镜像环境变量,避免在境外源上卡顿。
3.3 用配置文件启动vLLM服务
vLLM 提供了命令行启动方式,也可以写成配置文件,方便以后重复使用。一个典型的启动命令:
vllm serve /data/models/qwen-7b-chat-fp16 \ --served-model-name my-7b-chat \ --tensor-parallel-size 1 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9 \ --port 8000各参数含义后面会详细讲,这里先记住--gpu-memory-utilization 0.9表示允许 vLLM 使用 90% 的显存来缓存 KV Cache,这个比例不是越高越好,后面会解释原因。
启动成功后会输出一个 OpenAI 兼容的 API 地址,直接可以通过 HTTP 调用。
3.4 验证API是否可用
启动服务后,用curl做一次最基本的调用:
curl -X POST http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "my-7b-chat", "messages": [ {"role": "user", "content": "请简单介绍一下你自己"} ], "temperature": 0.7 }'能正常返回带有content字段的 JSON 响应,服务就算通了。后续接入业务系统时,用 OpenAI 客户端的写法直接改 base_url 就能对接,不需要改业务代码。
4. 轻量部署方案:Ollama跑通日常体验
如果只是内部几个人用,不想写代码、不想维护复杂框架,Ollama 是性价比最高的选择。它把模型权重管理、推理引擎、兼容API全封装好,安装完就能用。
4.1 什么时候不用vLLM而用Ollama
vLLM 虽然吞吐高,但配置项多,对新手不够友好。Ollama 最大的优势是“零配置”,一条命令就能拉起一个模型服务,而且自带模型管理功能,下载、更新、切换都非常方便。
代价是并发能力和吞吐上限不如 vLLM。如果只是个人调试、内部小范围试用,Ollama 完全够用;如果目标是支撑线上业务的高并发请求,还是建议用 vLLM。
4.2 安装Ollama并拉取模型
Linux 上安装 Ollama 的脚本很简单,装完以后直接拉取模型:
ollama pull qwen2.5:7b拉取完成后可以通过命令行交互:
ollama run qwen2.5:7b也可以启动一个常驻服务:
ollama serve默认监听本地 11434 端口,宿主机可以通过 127.0.0.1:11434 访问。
4.3 暴露OpenAI兼容接口给其他应用
Ollama 默认就提供了一套兼容 OpenAI 格式的 REST API,所以如果你的业务代码已经用了 OpenAI SDK,只需要修改两处:base_url指向 Ollama 服务地址,model名称改成 Ollama 里的模型名。
需要注意的是,Ollama 默认只监听 127.0.0.1,如果其他机器要访问,需要配置环境变量或用反向代理暴露。生产环境千万不要直接把端口裸暴露在公网,至少加一个鉴权层。
5. 显存不够时的应对策略:量化、上下文裁剪与多卡并行
显存不够是大模型部署中最常见的问题,几乎每个人都会遇到。处理方式有很多,但要按顺序来,不要一上来就上多卡。
5.1 量化:先压缩权重,用质量换显存
量化是把模型权重从高精度存储变为低精度存储。FP16 的 7B 模型权重需要约 14GB,INT4 量化后只需要约 4GB,省下来的显存能让 KV Cache 跑更大的上下文和更高的并发。
目前主流量化方案有 GPTQ 和 AWQ,两者在推理质量上差别不大,选择时主要看推理框架兼容性。vLLM 对这两种格式都支持得比较好。
我自己的建议是:先跑 FP16 确认效果符合预期,再跑量化对比质量损失。如果量化后效果能接受,就上量化;如果效果明显变差,再考虑多卡。
5.2 多卡并行:张量并行怎么工作
单卡放不下整个模型时,多卡并行是唯一选择。vLLM 中通过--tensor-parallel-size控制并行度,2表示将模型层切分到2张卡上同时计算。
多卡并行依赖卡间通信,如果是两张普通 PCIe 连接的卡,性能可能会受影响;如果服务器支持 NVLink 或类似高速互联,效果会好很多。实测中,同一个 70B 模型,在两张支持高速互联的 80GB 卡上跑,性能接近单卡跑该大小模型的预期水平,但普通 PCIe 连接的多个GPU有效带宽可能成为瓶颈。
启动命令示例:
vllm serve /data/models/qwen-70b-chat-fp16 \ --tensor-parallel-size 2 \ --max-model-len 4096 \ --gpu-memory-utilization 0.95.3 上下文长度的取舍
上下文长度直接影响 KV Cache 的显存占用。很多服务器并不是放不下模型,而是默认配置的max-model-len太大,导致 KV Cache 占满了显存。
例如一个 7B 模型 FP16 权重约 14GB,在 24GB 的单卡上,如果max-model-len设置为 32768,KV Cache 可能吃掉接近 6GB 以上,实际可用的并发窗口就被压缩了。如果业务场景根本不需要 32K 上下文,把max-model-len设为 4096 或 8192,可以明显提高并发能力。
6. 实测数据与关键参数调优
光说不练没有说服力。以下是我在固定硬件上做过的一组实测数据,配置为单张24GB GPU,部署 7B 级模型,vLLM 版本固定。数据仅供趋势参考,不同环境会有差异。
6.1 一组实测吞吐数据
| 配置 | 并发数 | 平均首Token延迟 | 综合吞吐Tokens/s |
|---|---|---|---|
| FP16, max-model-len=8192 | 1 | 约0.3s | 约30-45 |
| FP16, max-model-len=8192 | 8 | 约0.8s | 约80-120 |
| INT4量化, max-model-len=8192 | 8 | 约0.9s | 约70-110 |
可以看到,适量并发能显著提升总体吞吐,但每个请求的首Token延迟会略微上升。合理并发数通常不是越高越好,超过某个临界点后显存或计算资源会到瓶颈,延迟迅速恶化。
6.2 关键参数逐个说明
--gpu-memory-utilization控制 vLLM 可以使用多大比例的显存。设为 0.9 表示允许使用 90% 显存作为模型权重和 KV Cache 的预算,留出约 10% 给 CUDA context 和其他开销。设得太满容易触发奇怪的运行时错误,设得太低则 KV Cache 空间不够,并发上不去。
--max-model-len是单次请求允许的最大上下文长度。它会同时影响 KV Cache 预留和输入输出长度上限。调高这个参数前,先确认业务是否真的需要长上下文。
--max-num-seqs控制批处理窗口内的最大序列数量。默认值在多数场景下够用,但如果请求长度普遍很长,这个值可能需要调低,避免多个长请求同时挤进显存把 KV Cache 撑爆。
6.3 并发与延迟的取舍心得
线上服务如果追求交互体验,首Token延迟更重要,并发窗口不要开太大;如果是离线批量生成内容,可以把并发拉高来追求吞吐。
首Token延迟主要取决于模型大小、输入长度和排队情况,吞吐则取决于显存和计算资源规模。没有任何参数组合能同时把所有指标都拉满,部署者必须有意识地平衡。
7. 最容易踩的一组坑:完整排查思路
最后这部分,我整理了部署大模型时最常见的一批问题,按排查思路一步步拆解。很多问题表面看起来是同一个报错,实际原因可能完全不同,所以这里只给排查顺序,不直接给“标准答案”。
7.1 容器里看不到GPU
报错表现为:容器能启动,但nvidia-smi显示没有检测到设备,或 PyTorch 报 CUDA 不可用。
排查链路:
- 先确认宿主机
nvidia-smi是否正常,如果宿主机都看不到,说明驱动有问题; - 确认容器启动时是否加了
--gpus all参数; - 确认宿主机是否安装了
nvidia-container-toolkit并重启过 Docker; - 换个新镜像测试,排除镜像内工具缺失问题。
我遇到过最隐蔽的情况是:驱动版本偏旧,导致新版本容器内 CUDA 运行库无法与驱动通信。解决办法是看报错信息,提到driver、library相关字样时优先查驱动版本和镜像内 CUDA 兼容性。
7.2 显存明明够,却报显存溢出
这是最容易让人困惑的问题。表象是单卡24GB、模型权重14GB,按道理放得下,但启动时直接 OOM。
根本原因一般有两个。一是--max-model-len或并发配置过高,KV Cache 瞬间吃掉大量显存,叠加起来超了。二是显存碎片化,CUDA 分配显存时未必能拿到连续的大块空间。
排查顺序建议:
- 把
--max-num-seqs调到 1,--max-model-len调小,确认还能启动; - 如果能启动,说明模型本身可以放进去,问题出在 KV Cache 预留空间过大;
- 逐步调回参数,找到当前的临界值;
- 如果调到很小仍然 OOM,检查显存是否有其他进程占用,
nvidia-smi看内存占用情况; - 最后看是否加载了多个模型副本,旧进程是否真正释放了显存。
7.3 模型文件下载慢或失败
外层网络问题一般不属于部署逻辑,但确实是高频问题。遇到这种状况优先配置国内镜像源或改用国内模型托管平台,不要反复重试境外源。
另外要注意磁盘空间。大模型文件动辄几十GB,下载前先用df -h看目录剩余空间,避免下载到一半磁盘满了导致模型文件损坏。
7.4 API服务502或超时
服务启动时一切正常,但请求一段时间后开始超时,或者返回网络错误。排查思路:
- 先看服务进程是否还活着,是不是直接崩溃了;
- 再看日志里有没有显存 OOM 或线程池耗尽的信息;
- 然后调高
--max-num-seqs到合理范围,限制单批并发请求数量; - 如果单条请求上下文很长导致处理时间过长,考虑拆分请求或降低
max-model-len。
这类问题通常不是网络原因,而是服务端的资源或队列设计没有跟上请求模式,调整并发参数或给服务加一层排队保护就能解决。
同类的坑还有很多,比如 tokenizer 跑错模型、模板格式不一致导致回答异常、多卡并行时卡间通信超时等。处理思路都一样:先把环境和模型分开排查,确认模型本身没问题,再逐步检查框架参数和调用方式。部署大模型这件事,真正困难的从来不是某一条命令,而是对整条链路每个环节的理解。把这个链路走通一遍,后续面对任何新模型、新框架,心里都会踏实很多。