ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux下大模型部署实战:GPU显存评估与Ollama/vLLM调优

Linux下大模型部署实战:GPU显存评估与Ollama/vLLM调优 1. 为什么我建议你把大模型部署在Linux上先聊个实际场景。我手里有一台二手工作站双路E5处理器128G内存显卡是一张改过散热的RTX 3090 24G。最开始我想在Windows上跑大模型图省事结果光配CUDA、cuDNN、Python环境就折腾了一天半——版本不匹配、路径冲突、杀毒软件莫名其妙把我的权重文件隔离了最后还把系统搞蓝屏了一次。换到Linux之后全程没超过四十分钟。这不是说Windows跑不了而是大模型这套基础设施从CUDA驱动到容器运行时再到各个推理框架绝大部分都是优先适配Linux的。PyTorch官方安装命令Linux和Windows的差别不只是命令格式依赖库的处理逻辑完全不同TensorRT-LLM直接不支持原生WindowsvLLM虽然能跑但官方文档里连Windows的安装章节都写得含糊。做这行的人都懂一句话Linux是生产环境Windows是桌面环境。这篇博文面向谁两类人。第一类是算法工程师手里有训练好的模型或者开源权重想把模型部署到公司的GPU服务器上提供推理服务第二类是运维工程师被安排去搭建模型推理平台之前没接触过大模型相关的东西。文章里我尽量不写废话把从零到一的过程、命令、踩坑点都摊开讲。娱乐归娱乐干活归干活这篇是后者。2. 部署前的硬门槛硬件评估与显存计算2.1 显卡不是越贵越好先看显存和算力匹配大模型部署第一个关键问题是你手里的卡到底能跑多大的模型。这里有个最简单的估算公式模型占用显存约等于参数量乘以对应精度下的字节数再加上激活值、KV Cache和框架开销。以FP16精度为例1B参数大概占2GB显存7B参数就要14GB左右13B接近28GB32B需要64GB70B直接奔着140GB去了。注意这只是模型权重本身还没算推理过程中的中间缓存。所以很多人问“8G显存能不能跑7B模型”理论上有量化方案可以压缩到6GB以内但位宽越低输出质量越差这个后面细说。不同显卡的定位也要区分RTX 3060 12G / 4060 Ti 16G适合跑7B量化模型体验Qwen2.5-7B、Llama-3-8B这类RTX 3090 24G / 4090 24G黄金甜点卡能跑14B量化或者7B全精度个人开发者最常用的配置A100 40G / 80G、H100企业级可以跑70B量化或者多卡张量并行苹果M系列统一内存M2 Max 64G跑32B量化模型也能凑合但生态绕后面不展开。我的建议是先把模型规模定下来再决定用什么卡。模型超过10B24G显存是底线。2.2 CPU和内存同样不能忽视很多人把注意力全放在显卡上结果CPU和内存成了瓶颈。模型加载到显存之前要先把权重从磁盘读入内存再到显存。如果你的内存只有32G下了一个14B的模型FP16权重28G内存直接爆掉系统开始swap速度慢到怀疑人生。内存容量建议是模型权重的1.5到2倍128G内存是比较从容的配置。CPU的要求相对低一些但如果你用的是中低端消费级CPU在做prefill阶段处理输入token的时候CPU和内存带宽会拉低整体吞吐。实测下来消费级平台和服务器平台在同等GPU下单请求响应时间能差出20%到30%。还有个容易忽略的磁盘空间。现在主流开源模型权重动辄几十个GBQwen2.5-72B的FP16权重接近150G下之前先确认磁盘余量。模型文件建议放在SSD上机械硬盘加载一次70B模型光读盘就够你喝杯咖啡了。# 查看显存和GPU状态 nvidia-smi # 查看CPU和内存 lscpu | grep -E Model name|Core|Thread free -h # 查看磁盘剩余空间 df -h /data/models3. 模型选型与下载别只会去Hugging Face3.1 国内下载模型ModelScope比HF稳得多部署大模型第一步是拿到权重。Hugging Face作为全球最大的模型仓库国内访问经常超时断流下载几十GB的文件断了就得重来非常折磨人。我的建议是优先用ModelScope魔搭社区阿里的国内直连速度快下载稳定而且模型种类和HF基本同步。Qwen、Llama、DeepSeek、ChatGLM这些热门模型都有官方权重的镜像。如果一定要用Hugging Face有三个加速方案用hf-mirror.com镜像站把HUGGING_FACE_HUB_ENDPOINT环境变量指过去用hf_transfer库加速下载需要先pip安装再设置HF_HUB_ENABLE_HF_TRANSFER1先下载单文件再手动拼接适用于断点续传场景。ModelScope的命令行工具也很简单# 安装modelscope库 pip install modelscope # 下载Qwen2.5-7B-Instruct从魔搭下载 modelscope download --model Qwen/Qwen2.5-7B-Instruct --local_dir /data/models/Qwen2.5-7B-Instruct这里要提醒一下模型的版本、量化格式、对话模板差异巨大不要随便下个同名模型就往上套。比如Qwen2.5系列就有Base基座和Instruct指令微调两个大版本Instruct版自带对话模板是给聊天用的Base版更适合做下游微调或者当作embedding基座。你部署聊天服务应该选Instruct版本。3.2 量化模型是什么4-bit和8-bit怎么选经常看到有人问“为什么同一个模型有多个文件大小比如7B的有4GB、7GB、14GB”这其实是不同精度。14GB是FP1616位浮点7GB是INT88位整数4GB是INT44位整数。量化就是把模型权重从高精度压缩到低精度以牺牲一点质量为代价换来更小的显存占用和更快的推理速度。实际部署中我的经验是两个原则显存充足时优先用FP16或BF16全精度效果最好显存紧张时用INT8比INT4稳妥INT4有时候输出质量塌方尤其对数学、逻辑推理类任务特别明显。GGUF格式的量化模型通常用q4_K_M、q5_K_M、q8_0这些后缀表示不同量化级别q4_K_M是最常见的折中方案q8_0质量更接近FP16但体积大近一倍。市面上很多一键部署工具默认拉取的都是Q4量化版本。4. Ollama最省心的本地模型部署方式4.1 安装Ollama装完就能跑如果只想快速体验模型效果没有复杂的服务化需求Ollama是目前最省心的方案。它一个二进制文件搞定跑模型、提供API、管理模型生命周期对新手特别友好。Linux安装就一行命令curl -fsSL https://ollama.com/install.sh | sh装完之后启动服务systemctl start ollama systemctl enable ollama然后拉取模型运行# 拉取Qwen2.5-7B-Instruct的Q4量化版本 ollama pull qwen2.5:7b # 运行模型进入交互式对话 ollama run qwen2.5:7b第一次运行会自动下载权重国内网络如果下载慢可以设置环境变量OLLAMA_MODELS指定模型存放目录再用代理或者镜像加速。注意Ollama默认模型存储在/usr/share/ollama/.ollama/models如果系统盘空间小建议提前改路径# 修改Ollama模型存储路径写入环境变量 mkdir -p /data/ollama-models echo OLLAMA_MODELS/data/ollama-models /etc/environment systemctl restart ollama4.2 换模型和查模型很简单Ollama的模型管理命令非常直观# 查看本机已下载的模型 ollama list # 删除不用的模型 ollama rm qwen2.5:7b # 从已有modelfile创建自定义模型另外一个很多人不知道的细节Ollama原生提供OpenAI兼容的API接口端口是11434。你的应用代码只要把base_url换成http://服务器IP:11434/v1把api_key随便填个字符串就能直接用OpenAI的SDK接入本地模型了。这意味着之前写的调用OpenAI接口的代码几乎零改动就能切换到本地。# 验证API是否正常 curl http://localhost:11434/v1/models # 调用聊天接口 curl http://localhost:11434/v1/chat/completions \ -H Content-Type: application/json \ -d { model: qwen2.5:7b, messages: [{role: user, content: 你好介绍一下你自己}] }5. 更灵活的Docker部署GPU透传和镜像选择5.1 为什么推荐Docker环境和版本隔离是关键Ollama虽然省事但如果你想部署多个模型、多个推理框架或者和别人共用同一台服务器直接用宿主机环境很容易搞成“依赖地狱”——这个库要这个版本那个库要另一个版本还要互相冲突。Docker能完美解决这个问题。每个容器有自己的运行环境互不干扰。而且NVIDIA官方提供了nvidia-container-toolkit可以让容器直接使用宿主机GPU物理性能损耗只有个位数百分比几乎可以忽略。在Linux上部署Docker GPU环境的完整步骤# 1. 安装Docker以Ubuntu 22.04为例 curl -fsSL https://get.docker.com | sh # 2. 安装NVIDIA Container Toolkit distribution$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list sudo apt-get update sudo apt-get install -y nvidia-container-toolkit # 3. 重启Docker sudo systemctl restart docker # 4. 验证GPU能否被容器识别 docker run --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi如果第四步能正常输出GPU信息说明环境OK。这一步我建议所有人部署前先验证能省掉后面排查问题的大把时间。5.2 用Docker跑Ollama和vLLMOllama官方也提供了Docker镜像直接拉起来用docker run -d --gpus all -v /data/ollama-models:/root/.ollama \ -p 11434:11434 \ --name ollama \ ollama/ollama这里解释一下参数含义-d是后台运行--gpus all把全部GPU传给容器-v做了目录挂载把容器的模型目录映射到宿主机的/data/ollama-models这样模型权重在宿主机也能看到以后重装容器数据不丢。-p把容器的11434端口映射到宿主机。如果是追求高吞吐的生成式AI服务用vLLM更合适。vLLM是当前最流行的推理加速框架通过PagedAttention、连续批处理等技术显著提升吞吐量。部署方式照样用Dockerdocker run --gpus all \ -p 8000:8000 \ -v /data/models:/models \ vllm/vllm-openai:latest \ --model /models/Qwen2.5-7B-Instruct \ --served-model-name qwen2.5 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9这里提一个非常重要的概念gpu-memory-utilization意思是允许vLLM最多吃满90%的显存。留出10%的余量是为了防止OOM显存溢出。如果你把值设成0.95然后同时来几个长对话请求很容易直接OOM崩溃。还有max-model-len它决定模型支持的最长上下文长度设的越大KV Cache占显存越大在7B模型上从4096改成16384显存占用能多出3到4GB要根据实际需求权衡。6. 踩坑实录从部署到调优的9个高频问题部署过程中我踩过不少坑这里整理一个高频问题速查表你如果遇到类似问题直接对照排查。现象可能原因解决办法docker运行提示无GPUnvidia-container-toolkit未安装或Docker未重启安装toolkit后必须systemctl restart dockerOllama响应特别慢模型未完全加载到显存还在用CPU推理检查nvidia-smi显存占用确认显存充足中文输出乱七八糟没走对话模板或者模型选错版本使用Instruct版本检查API请求是否正确构造messages格式端口被占用11434或8000已被其他程序占用lsof -i:11434查看占用改端口或kill进程显存OOM并发请求太多或max-model-len设置过大降低并发数减小max-model-len调低gpu-memory-utilization下载模型经常中断网络不稳定或连接被重置用ModelScope下载后手动导入Ollama模型回答内容重复啰嗦温度参数设置太高或未设置使用默认temperature或调低到0.7以下多卡服务器只用了1张卡Ollama默认只使用一张GPU设置环境变量OLLAMA_NUM_GPUallserver部署vLLM后接口503模型还在加载中或者显存不足查看日志等待加载完成或换更小模型特别说一下模型导入Ollama的问题。你从ModelScope手动下载回来的模型不是直接扔进某个文件夹就能被Ollama识别。正确流程是用Modelfile来导入。如果你下载的是GGUF格式的模型文件Modelfile内容就一行FROM ./qwen2.5-7b-instruct-q4_k_m.gguf然后执行ollama create qwen2.5:7b-q4 -f Modelfile之后再运行ollama run qwen2.5:7b-q4就可以了。7. 模型微调让大模型更懂你的业务7.1 微调不是从零训练参数高效微调才是主流部署只是开始。当开箱即用的通用大模型无法满足特定业务需求时就得考虑微调。比如你做一个法律问答助手Qwen2.5-7B通用版对法律条款的回答可能泛泛而谈你需要用真实的法条问答对去让它“变得更专业”。微调不是从零训练而是基于预训练权重继续学习。主流方式是参数高效微调其中最常用的是LoRALow-Rank Adaptation低秩适配。它的核心思想是冻结原始模型的全部参数只训练一小部分新增的低秩矩阵显存和算力需求直接降一个数量级。原来微调7B全参可能需要80G显存用LoRA 量化之后24G显存就能跑。业界经常用Unsloth这个库来做微调它的口号是“2倍速度、50%显存占用”在开源社区口碑很好。一个完整的Unsloth微调脚本结构大概是这样from unsloth import FastLanguageModel import torch # 加载模型和分词器自动启用4-bit量化 model, tokenizer FastLanguageModel.from_pretrained( model_nameQwen/Qwen2.5-7B-Instruct, max_seq_length2048, load_in_4bitTrue, ) # 注入LoRA适配器 model FastLanguageModel.get_peft_model( model, r16, # LoRA秩越大表达能力越强但计算量也越大 lora_alpha16, # 缩放系数 lora_dropout0, # 实测设为0通常效果更好 biasnone, use_gradient_checkpointingTrue, ) # 加载数据集 from datasets import load_dataset dataset load_dataset(json, data_filesyour_data.jsonl, splittrain) # 定义训练参数 from trl import SFTTrainer from transformers import TrainingArguments trainer SFTTrainer( modelmodel, tokenizertokenizer, train_datasetdataset, argsTrainingArguments( per_device_train_batch_size2, gradient_accumulation_steps4, learning_rate2e-4, num_train_epochs3, output_diroutput, fp16torch.cuda.is_bf16_supported(), logging_steps10, save_strategysteps, save_steps100, optimadamw_8bit, ), ) trainer.train()7.2 微调数据长什么样经验与常见误区微调效果最大化数据质量比数据量更重要。我自己用下来几千条精心构造的指令数据效果可能好过几万条爬来的脏数据。数据格式以JSONL为例每条包含instruction指令、input输入可空、output期望输出{instruction: 解释什么是合同解除, input: , output: 合同解除是指合同有效成立后因一方或双方当事人的意思表示使合同关系归于消灭的行为...} {instruction: 根据以下案情判断是否构成违约, input: 甲与乙签订供货合同约定甲于3月1日前交货甲未能按期交货。, output: 构成违约。甲未按合同约定的时间履行交货义务...}很多新手容易犯的错误把预训练语料直接拿来微调对话模型结果训练完模型说话前言不搭后语。原因是格式不对——指令微调要求的是“问题-回答”这种结构化格式而不是纯粹的文本续写。另外微调完的模型部署方式也有区别LoRA的adapter权重是依附在原模型上的用vLLM部署时需要额外指定--enable-lora和--lora-modules用Ollama则需要导入合并后的完整权重不能只放adapter文件。8. 并发与性能调优从“能跑”到“跑得好”8.1 Ollama和vLLM的性能差异部署完成、能出结果只是第一步。线上服务面对真实流量时并发能力是关键。我拿Qwen2.5-7B-Instruct做过实际对比单张RTX 4090Ollama默认配置下单请求延迟大概40ms/token吞吐量约25 token/svLLM开启连续批处理后同一模型在8并发下单请求延迟虽然涨到200ms但整体吞吐能到150 token/s以上。这说明Ollama适合个人开发和低并发场景vLLM适合真正对外提供服务。如果你的并发需求不高同时只有几个人用Ollama加OLLAMA_NUM_PARALLEL环境变量调整并发worker数就够了。要是给全公司提供服务老老实实上vLLM。vLLM还支持流式输出、前缀缓存等特性对聊天体验提升非常明显。# Ollama并发配置示例设置同时最多处理4个请求 echo OLLAMA_NUM_PARALLEL4 /etc/environment systemctl restart ollama8.2 用“一句顶一万句”的OpenAI兼容层做统一接入现在很多类似于云厂商的模型服务都实现了OpenAI兼容接口好处是你的服务可以用一套标准接口接入不同后端想切换模型时改个URL就行。以vLLM启动的服务为例它默认监听8000端口接入代码只需要这样写from openai import OpenAI client OpenAI( base_urlhttp://10.0.0.5:8000/v1, # 换成你的服务器IP api_keyEMPTY, # 本地部署不校验key但字段不能省略 ) response client.chat.completions.create( modelqwen2.5, messages[ {role: system, content: 你是一个友善的助手。}, {role: user, content: 请介绍一下Linux服务器部署大模型的步骤}, ], temperature0.7, streamTrue, # 开启流式输出 ) for chunk in response: if chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end)这段代码是最常用的流式对话输出用户体验好不会让人对着一个转圈圈的空页面干等。使用OpenAI兼容层也是目前把所有主流推理框架接入统一层的最佳实践。8.3 实测下来的一些经验数值多次测试之后我总结出几个比较靠谱的经验值7B Q4模型在24G显存上理论能支撑20路并发问答但效果会随着并发数增加明显下降70B Q4模型在双卡80G服务器上做张量并行首token时延从单卡的2400ms降到900ms左右max-model-len设成8192的7B模型KV Cache大约占3GB显存如果调到32768光这一项就是12GB心里要有数开启vLLM的--enable-prefix-caching之后对于多轮对话场景重复前缀的token计算量可以减少30%左右。调优没有银弹建议先跑通默认配置然后逐步调整参数观察吞吐和显存曲线。关于监控推荐用nvidia-smi做一个crontab定时采样# 每5秒记录一次GPU状态持续半小时 nohup nvidia-smi --query-gpuutilization.gpu,memory.used,temperature.gpu --formatcsv -l 5 gpu_monitor.log 21 9. 最后说几句实在话我在这个领域调试了快两年一个非常深的体会是大模型部署的坑大部分不是模型的坑而是基础设施的坑。CUDA版本不匹配、GLIBC版本太老、磁盘被日志写满、防火墙拦了端口、DNS解析失败每个看起来是小问题排起来都能吃掉一整天。与其祈祷不出错不如一开始就把环境管控好——能用Docker尽量用Docker依赖全部锁版本磁盘和内存提前规划容量。另外一个很多人问我的问题“我应该用Ollama还是vLLM”我的回答是看场景。个人学习、本地知识库、给三五个人用Ollama够了简单到像在用一个工具而不是部署一个系统公司里对外提供API或者要接比较复杂的业务逻辑直接上vLLM并发吞吐和稳定性都有保障。两者并不互斥同一台机器上完全可以同时跑用不同端口隔离。如果你刚开始接触我的建议是从Ollama跑一个7B或8B的Instruct模型开始花一个晚上把API调通然后用Python写个web服务壳子把自己的业务数据接进来。这条路走通之后再去研究vLLM换掉Ollama后端就顺理成章了。别一上来就想部署70B大模型那是另外一套完全不同的游戏。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进