我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

Ubuntu上部署千问大模型:从显存估算到vLLM与量化调优全流程

Ubuntu上部署千问大模型:从显存估算到vLLM与量化调优全流程 把开源大模型部署在自己的Ubuntu机器上这事儿放在两年前听着还挺极客现在已经是常规操作了。我这两周把千问系列模型从0.5B到72B都各跑了一轮踩遍了显存爆掉、驱动失配、量化格式选错这些坑最后整理出一套能在不同硬件条件下直接照抄的完整流程。这篇文章就以千问2.5系列Qwen2.5的7B Instruct版本为主线把部署步骤里的关键决策点、参数选择逻辑和排错经验一次性讲透。这篇文章适合这么几类人手头有一块6GB以上显存GPU的开发者想在公司内网搭一个私有问答服务、又不想调外部API的运维或算法工程师纯好奇想在宿舍电脑上把大模型“跑起来”的学生。读完之后你至少能搭出两条可用的路线——一条是面向高并发生产场景的vLLM路线一条是面向个人电脑轻量使用的本地快速路线。两条路线的每一步我都会给出可以直接执行的命令和参数。先说一句总结性的判断千问系列在开源大模型里属于综合表现很能打的一支模型覆盖面从边缘设备到多卡服务器都够用。但正因为选择太多很多人第一步就卡在“选哪个模型、用哪个框架、配什么硬件”上。我接下来的顺序就是按照一个完全没接触过本地部署的人从零开始把这套东西跑通来安排的。1. 部署前的思路梳理先想清楚再动手1.1 千问系列模型怎么选参数量不是越大越好千问2.5系列常见的参数量档位包括0.5B、1.5B、3B、7B、14B、32B、72B另外还有MoE结构的版本。对应到实际需求思路其实很简单你的显存决定了你能跑多大模型你的任务复杂度决定了你至少需要多大模型。0.5B到1.5B适合做简单文本分类、关键词提取、格式化输出这类任务。说句实在话这类模型拿来正经做对话或写文章效果还是比较抽象但胜在可以在CPU上跑树莓派级别的设备也能带得动。3B到7B是个分水岭7B Instruct在对话质量、指令理解、代码生成上已经能看出真正的大模型能力也是目前社区里生态最完善的档位。14B和32B需要24GB以上的显存如果用4bit量化则可以把门槛降到大约8GB到16GB。72B基本属于服务器级应用场景至少需要一张80GB显存的卡或者用多卡并行。我给新手的建议是不要一上来就挑最大型号。先拿7B的量化版把整个部署链路跑通包括模型加载、请求封装、推理服务启动再根据实际效果往上升级模型。部署过程和模型参数量关系不大换模型只是改一个路径的事但如果在第一步就卡在显存上会很挫败。1.2 三条主流部署路线怎么取舍vLLM、Ollama、llama.cpp同样是把千问模型跑起来社区里有三条路线最常用三者的定位差异很大。我分别说一下它们适合的场景。vLLM是目前生产环境中最主流的方案核心优势是PagedAttention和Continuous Batching。前者把KV Cache分块管理显存利用率更高后者让多个请求可以在同一个批次里动态调度并发吞吐量远超朴素的推理脚本。代价是安装体积较大、对GPU显存有一定要求、Python环境需要梳理干净。Ollama是个人电脑上最友好的方案安装一个二进制文件两条命令就能把模型拉下来并跑起来自带OpenAI兼容API和内置的模型管理。它内部也做了不少优化比如自动选择GPU层数、跨平台支持。适合不想折腾环境、只想尽快用上模型做实验的人。llama.cpp是底层派的代表没有Python依赖纯C/C实现支持CPU推理和GPU加速主打通过GGUF格式做各种量化。如果你需要极致抠显存、跑老显卡甚至纯CPU环境这条路几乎是唯一选择。代价是功能相对底层安装编译的步骤多一点。三条路线的选择逻辑很简单生产并发服务选vLLM个人娱乐和原型验证选Ollama硬件受限或者想深入理解量化原理选llama.cpp。我接下来会分别给出三条路线的实操步骤并重点讲透vLLM因为这是最接近真实工程场景的方案。1.3 显存估算与硬件门槛用数学提前避坑部署大模型最怕的就是启动之后没跑几分钟就OOMOut of Memory。这个坑完全可以通过启动前估算来规避。核心公式其实很简单模型权重占用显存 参数量 × 每个参数占用的字节数以FP16/BF16精度为例每个参数占2字节那么7B模型权重就要占约14GB。14B模型则是28GB。前面说的这个公式只是权重大小推理时还需要额外空间存放KV Cache、激活值和CUDA上下文实际占用一般是权重的1.2到1.4倍。所以跑7B的FP16版本稳妥的显存底线是16GB到20GB跑14B则建议至少32GB。如果显存不够量化是唯一的出路。常见量化精度包括INT8和INT4对应每参数占用1字节和约0.5字节。4bit量化的7B模型权重直接降到约4GB左右配合KV Cache和中间变量8GB显存的卡也能勉强跑起来只是输出速度会有所下降。拿我自己一台机器的实测数据举例在一块12GB显存的GPU上用vLLM跑Qwen2.5-7B-Instruct的FP16版本最大上下文长度8Kgpu-memory-utilization设为0.90最终KV Cache总量约1.8GB显存占用峰值约15.4GB所以12GB的卡其实跑不动。换上AWQ 4bit量化版之后权重占用约4.5GB峰值约8.6GB就能稳跑了。这就是选型时为什么要先看显存再看模型参数量。2. 系统环境准备把地基打牢2.1 Ubuntu系统基础配置与必要工具部署环境我使用的是Ubuntu 22.04 LTS这个版本对Python 3.10和主流深度学习框架的支持都比较完整也是目前社区里测试最充分的操作系统版本。如果你还在用18.04我建议先升级系统再往下走否则后续依赖很容易出版本兼容问题。系统层面的准备分三步。第一步是更新软件源并安装基础工具包括curl、git、build-essential、cmake等编译工具链。第二步是检查GPU是否被系统正确识别方法是运行lspci | grep -i nvidia能看到显卡型号说明系统已经拿到了硬件信息。第三步是安装NVIDIA驱动和CUDA工具链这个环节最容易出问题我在下一节详细讲。sudo apt update sudo apt upgrade -y sudo apt install -y curl git build-essential cmake net-tools htop这套基础工具后面都会用到git用来拉取开源代码cmake和build-essential在编译llama.cpp时需要htop则是监控CPU和内存占用的利器。系统准备阶段不用装太多东西保持干净的环境比什么都重要。2.2 GPU驱动与CUDA环境安装版本匹配是关键很多人在这一步就翻车了原因在于NVIDIA驱动和CUDA Toolkit是两回事。驱动是显卡和操作系统之间的桥梁CUDA Toolkit是编译和运行GPU代码的开发库。vLLM、PyTorch这类框架运行时底层需要的是驱动加CUDA运行库的组合。我的建议是先装驱动再装CUDA Toolkit而且直接把CUDA环境交给conda或Python包来处理不强行装全套系统级CUDA。具体操作是先用nvidia-smi查看驱动支持的CUDA版本确认驱动已经工作。如果没有驱动可以用系统自带的ubuntu-drivers工具自动安装sudo apt install -y ubuntu-drivers-common sudo ubuntu-drivers autoinstall sudo reboot重启后再看nvidia-smi正常输出类似这样----------------------------------------------------------------------------- | NVIDIA-SMI 535.104.05 Driver Version: 535.104.05 CUDA Version: 12.2 | -----------------------------------------------------------------------------注意右上角的CUDA Version并不代表你已经装了CUDA Toolkit它只是告诉你当前驱动最高支持到哪个CUDA版本。编译模型或安装vLLM时框架会自动携带对应的CUDA运行库所以驱动支持的版本只要不低于框架要求的版本就行。2.3 Python虚拟环境与依赖管理隔离比省事重要Python环境建议直接用Miniconda管理不要用系统自带的Python直接装深度学习包。理由很简单大模型相关的依赖版本锁得很死系统Python稍微动一下就会牵连到系统工具。Miniconda体积小装起来不污染系统环境创建和销毁也方便。wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh source ~/.bashrc装完之后创建一个独立环境Python版本选3.10或3.11都可以目前主流推理框架对这两个版本的兼容性最好conda create -n qwen python3.10 -y conda activate qwen之后的模型下载、框架安装、推理服务全部在这个名为qwen的环境里进行。每次新开终端都要记得先激活环境这一步漏掉的话后面会出现各种莫名其妙的ModuleNotFoundError。3. 模型权重获取选对渠道少走弯路3.1 认识模型文件原始权重、GGUF、GPTQ/AWQ进入下载环节之前先花点时间搞清楚模型文件的不同形态这决定了你后面能不能被对应框架识别。最常见的形态是原始权重目录也就是HuggingFace格式的模型仓库里面包含safetensors格式的张量文件、config.json配置、tokenizer.json分词器等。vLLM和transformers都直接吃这种格式。第二种是GGUF格式主要配合llama.cpp家族使用。GGUF把模型的权重和分词器打包到一个文件里便于分发和加载并且可以在打包时就完成从FP16到4bit的量化是CPU推理和低显存场景的首选。第三种是GPTQ和AWQ格式。这两种都属于面向GPU推理的量化格式在GPU上加载后能显著降低显存占用同时保持不错的推理速度。对显存不够但又想用vLLM跑更大模型的人来说选择对应版本的AWQ或GPTQ模型文件是最优解。选择格式时只需要记住用vLLM做生产服务优先选原始FP16或对应量化版本用Ollama直接使用Ollama库内已经转好的量化版本用llama.cpp下载GGUF格式。3.2 从开源模型平台拉取权重一条命令搞定千问系列模型在多个开源模型平台都有完整镜像仓库我这里习惯使用ModelScope平台魔搭社区因为下载速度和稳定性都很好也支持Python SDK断点续传。如果你的网络环境对大文件下载不友好用官方SDK比直接git clone稳很多。先安装依赖然后可以直接写一个下载脚本pip install modelscopefrom modelscope import snapshot_download # 只需要改下面这一行就能切换不同型号 model_dir snapshot_download( Qwen/Qwen2.5-7B-Instruct, cache_dir/data/models, resumeTrue ) print(f模型已下载到: {model_dir})这段代码会把模型权重完整拉到/data/models目录下。resumeTrue表示支持断点续传大文件下载中断了也不用重新来。我这里说一句经验之谈下载模型前先检查磁盘剩余空间用df -h /data看一下一个7B原始权重就要占用约15GB空间别下到一半把磁盘塞满了。3.3 目录规划与文件校验养成好习惯模型文件的目录规划值得从一开始就做好不然以后管理多个模型时会很头疼。我的习惯是统一放到/data/models下面每个模型以模型名/参数量/格式为子目录层级放置。比如/data/models/ └── Qwen2.5-7B-Instruct/ ├── config.json ├── model-00001-of-00008.safetensors ├── model-00002-of-00008.safetensors ├── ... ├── tokenizer.json └── tokenizer_config.json下载完成后建议检查一下文件完整性。主要看两方面第一配置文件里指定的分片数量和实际下载的safetensors文件数量是否一致第二模型仓库发布的SHA256校验值是否匹配。多数平台提供模型文件的索引信息你可以在下载后用一个简单的脚本做校验pip install huggingface_hub python -c from huggingface_hub import snapshot_download snapshot_download(repo_idQwen/Qwen2.5-7B-Instruct, local_dir/data/models/Qwen2.5-7B-Instruct) 其实这行命令也可以替代前面的Python脚本完成下载两个渠道任选其一即可。核心思路是通过平台SDK下载不要手动一个个点文件否则慢到怀疑人生。4. 基于vLLM的千问模型完整部署生产级方案4.1 安装vLLM与验证环境vLLM的安装非常直接在刚才创建好的conda环境里执行即可pip install vllm pip install accelerate安装过程会拉取PyTorch、CUDA Toolkit等大型依赖需要几分钟时间。装完后先做两步验证第一步确认vLLM版本与当前CUDA驱动兼容第二步运行一个最小的推理测试确保环境可用。python -c import vllm; print(vllm.__version__)如果输出正常的版本号比如0.6.x说明导入成功。真正验证推理能力时可以先用一个小模型跑一下但我个人建议直接进入正题用7B模型做完整测试因为它的加载时间也不算长。vLLM对GPU架构有要求需要具备一定的算力等级也就是Compute Capability 7.0以上。如果你拿的是特别老的显卡建议改用llama.cpp路线。可以用下面的命令确认自己的显卡算力等级python -c import torch; print(torch.cuda.get_device_capability(0))4.2 启动OpenAI兼容API服务参数逐个讲透vLLM最方便的地方是自带OpenAI兼容API服务启动之后你就可以直接用requests、openai库来调用跟调用云端API的方式几乎一样。启动命令如下python -m vllm.entrypoints.openai.api_server \ --model /data/models/Qwen2.5-7B-Instruct \ --tensor-parallel-size 1 \ --gpu-memory-utilization 0.90 \ --max-model-len 32768 \ --port 8000 \ --served-model-name qwen2.5-7b这里把常用参数逐个说一下。--model指向本地下载好的模型目录vLLM会自动读取配置并加载权重。--tensor-parallel-size是张量并行度如果你的机器有多张GPU可以设置成对应的数量让模型权重切分到多卡上。一块卡就保持1。--gpu-memory-utilization是最需要关注的参数它表示vLLM最多可以使用多少比例的显存。默认值是0.9如果推理过程中出现OOM就降到0.8或者0.7。这个值不是越大越好留一点显存给CUDA上下文和其他进程才能更稳妥。--max-model-len控制最大上下文长度也就是模型能一次性处理的最大token数。7B模型一般支持32K的上下文但上下文越长KV Cache占用指数级增加。所以如果你的显存比较紧张把这个值调小是最直接的省显存方式。--port是API服务监听端口--served-model-name是你自定义的模型访问名称。前者影响客户端连接后者影响OpenAI请求体里的model字段。启动后如果一切正常终端会打出类似下面的日志INFO: Started server process [12345] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000看到Uvicorn running服务就起来了。4.3 客户端调用与并发测试验证服务真的可用服务启动之后用curl做一次最基本的对话测试curl http://localhost:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: qwen2.5-7b, messages: [{role: user, content: 请用一句话介绍你自己}], max_tokens: 200 }正常情况下会返回一段JSON其中choices[0].message.content就是模型的回答。响应结构里的usage字段也很重要它告诉了你这次请求消耗的prompt_tokens和completion_tokens可以用来估算上下文开销。如果想模拟生产环境里的多用户并发可以写一个小脚本用线程池同时发多个请求import concurrent.futures import requests import time PROMPT 用三句话解释什么是大语言模型 def call_once(_): resp requests.post( http://localhost:8000/v1/chat/completions, json{ model: qwen2.5-7b, messages: [{role: user, content: PROMPT}], max_tokens: 256 }, timeout60 ) return resp.status_code start time.time() with concurrent.futures.ThreadPoolExecutor(max_workers8) as executor: results list(executor.map(call_once, range(32))) print(f耗时: {time.time() - start:.2f}s, 全部成功: {all(r 200 for r in results)})在7B模型上8路并发、32个请求的测试通常能在几十秒内全部返回。如果你的请求耗时明显异常那就要检查一下显存是否被模型权重占满了或者上下文长度设置得是否过大了。5. 轻量级部署路线Ollama与llama.cpp实测对比5.1 Ollama快速部署两条命令跑通对话如果说vLLM是重武器Ollama就是一把轻便的手枪。想省事的人可以直接用Ollama它把模型下载、推理引擎、API服务全部封装好了。安装只需要一条命令curl -fsSL https://ollama.com/install.sh | sh安装完成后拉取千问7B模型并直接运行交互对话ollama pull qwen2.5:7b ollama run qwen2.5:7b到这里你已经能在终端里跟千问对话了。Ollama默认会自动下载一个适合当前硬件的量化版本所以对硬件的兼容性比vLLM温和得多。如果要用API方式调用Ollama同样提供OpenAI兼容接口默认端口是11434ollama serve然后在另一个终端里请求curl http://localhost:11434/v1/chat/completions \ -H Content-Type: application/json \ -d {model: qwen2.5:7b, messages: [{role: user, content: 你好}]}Ollama对个人电脑用户非常友好唯一让我觉得不太爽的是底层推理能力的控制粒度很粗很多高级参数拿不到生产环境里的高并发优化也比较有限。但作为原型Demo或个人工具它的省心和稳定是无可替代的。5.2 llama.cppCPU和低显存场景的“救火队员”如果你的机器没有独立显卡或者只有一块显存很老的卡ollama内部其实也能走CPU但效率和可控性不如直接用llama.cpp。llama.cpp通过GGUF格式把量化做到极致实测在16GB内存的纯CPU机器上跑7B Q4量化模型大概能每秒输出4到6个token写个短代码、中英互译够用。编译安装先从GitHub克隆源码然后配置编译选项git clone https://github.com/ggml-org/llama.cpp cd llama.cpp cmake -B build -DGGML_CUDAON cmake --build build --config Release -j $(nproc)如果你的机器没有NVIDIA GPU就不要加-DGGML_CUDAON纯CPU编译会简单很多。编译完成后需要下载GGUF格式的千问模型比如qwen2.5-7b-instruct-q4_k_m.gguf。下载好后用命令行启动交互对话./build/bin/llama-cli \ -m /data/models/qwen2.5-7b-instruct-q4_k_m.gguf \ -p 请用一句话介绍你自己 \ -n 128-n表示生成的最大token数-p是用户输入的提示词。如果想启动一个服务供其它程序调用可以使用llama-server命令它同样提供OpenAI兼容接口./build/bin/llama-server \ -m /data/models/qwen2.5-7b-instruct-q4_k_m.gguf \ --host 0.0.0.0 \ --port 80805.3 三条路线的选型建议别拿大炮打蚊子部署方式和场景强相关我个人的经验是如果只是为了自己玩用Ollama如果确定要对外提供接口服务且并发量不算太大vLLM足够强大如果是内网离线环境、硬件资源极其有限llama.cpp GGUF是最后的底线方案。三者的资源占用从高到低排序vLLM最重Ollama适中llama.cpp最轻。但同时反过来vLLM的吞吐能力、对请求的调度策略和生态集成是另外两个框架暂时比不上的。建议新手在本地先把三条路线都体验一遍每个都只需要半小时左右跑通之后你对整个大模型推理链路有更立体的理解后面做任何技术选型都不会发虚。6. 部署后的性能调优与问题排查实录6.1 常见错误速查表亲测有效的解决方案部署过程中遇到的错误翻来覆去就那么几类我把最常见的整理成一张速查表基本上照着排查就能解决。错误现象根本原因解决方案启动即报CUDA out of memory模型权重KV Cache超出显存调低gpu-memory-utilization或调低max-model-len或换4bit量化模型API请求返回400 Bad Request请求的model字段与服务端served-model-name不一致核对请求体里的model是否和启动参数里的名字一致Token数量超过上限输入输出的总长度超过max-model-len增大max-model-len或限制请求的max_tokens模型加载时报weight dtype mismatch下载的模型版本与vLLM/PyTorch版本不兼容升级vLLM到最新版或者改用官方明确标注支持的模型版本Ollama pull时下载到一半卡住网络波动导致大文件下载中断重新执行ollama pullOllama会基于已有的部分文件继续下载Token输出速度极慢量化过低或CPU推理纯CPU环境下换用Q4_K_M量化GGUF并确保没有其他高负载程序抢占内存torch.cuda.is_available()返回FalsePyTorch安装的是CPU版卸载后重新安装CUDA版PyTorch即pip install torch --index-url对应CUDA版本在排查时有一条通用的思路先看dmesg | tail -50有没有GPU相关的报错再检查nvidia-smi里显存和GPU利用率最后看推理框架自己的日志。大部分问题都能在这三步里找到线索。6.2 性能优化让模型跑得更快、更稳模型部署成功只是第一步想要在生产环境里用得爽还有三个优化方向值得做KV Cache优化、连续批处理和量化精度选择。关于KV Cache前面提过它是限制并发和上下文长度的核心因素。vLLM的PagedAttention本质上就是给KV Cache做了分页管理所以你不需要手动控制太多细节但显存紧张时可以通过缩小--max-model-len直接减少KV Cache预算。实测同样一块12GB显卡从32K上下文降到8K显存占用能省出3GB以上。关于连续批处理如果你用的是vLLM这个功能已经默认开启。要注意的是并发请求越多、单个请求长度越短吞吐优势越明显。如果你发现自己之后要处理大量长文档那连续批处理的收益就不如短请求场景大。量化精度的选择其实是在效果和性能之间做权衡。FP16效果最好但吃显存INT8效果损失很小且显存占用减半INT4会产生比较明显的效果回落。我的建议是显存足够就无脑用FP16显存差一点先用INT8实在跑不动再降INT4。6.3 几个值得记住的部署细节最后分享几个部署里的细节都不是什么大事但每一个都曾经卡住过我好一阵。第一启动vLLM的时候如果发现模型加载特别慢试一下给/data/models所在磁盘换个读取速度更快的位置。模型加载本质上是大量小文件读取机械硬盘会非常吃亏SSD和内存盘的速度差距是数量级的。第二如果遇到输出内容莫名重复、逻辑混乱的现象先别怀疑模型出了问题。多数情况下是因为上下文长度超了但服务端截断了参数或者量化精度太低导致的“幻觉”。优先降低并发时的输入超长请求再看量化档位。第三大模型服务跑起来之后一定要用进程守护工具托管比如systemd或tmux。直接在终端里前台跑服务的风险在于一旦终端会话断开服务就跟着停掉了。我自己的习惯是用tmux创建一个常驻会话把服务放到后台运行这样即使远程工具断开服务也依然在运行。第四日志一定要留存。在启动命令后面加上标准的日志重定向比如21 | tee /var/log/qwen-server.log排查问题时就会发现这些日志真的很救命。结尾就我个人的体验来说整个部署链路最消耗耐心的环节反而是下载权重和匹配环境真正运行起来反而不容易出问题。如果非要用一句话总结心得那就是先把最小可行链路跑通再逐步叠加并发、调优和模型升级。不要一开始就追求72B多卡超长上下文先把一条简单路线跑稳后面想怎么折腾都来得及。最后再分享一个小技巧部署好之后你可以顺手写一个简单的记录脚本把每次请求的prompt_tokens、completion_tokens、耗时、显存峰值记录下来。跑一段时间之后这些数据会帮你很直观地判断当前配置是否需要升级以及瓶颈到底出在模型、显存还是并发上。这个习惯比收藏各种调优参数都管用。
返回列表