尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

飞腾D3000上部署文心大模型:从环境准备到推理优化全记录

飞腾D3000上部署文心大模型:从环境准备到推理优化全记录 1. 项目概述与方案选型1.1 这项目到底在做什么飞腾腾锐D3000这是飞腾新一代的桌面级处理器采用ARM架构主频、核心数、内存通道这些指标相比前代都有了明显提升。过去这两年我在国产CPU平台上折腾过不少东西从简单的Web服务到数据库、中间件都跑过但真正把大模型推理跑起来这还是第一次比较完整的实践。文心大模型是百度自研的生成式大语言模型常见的有ERNIE系列包含不同参数规模的版本。普通的做法是直接调用云端API但现在很多场景要求数据不出内网、完全离线就必须自己部署一套推理环境。飞腾D3000所在的这种国产化硬件平台恰恰是这类需求高发的地方——政务、金融、能源这些行业采购的终端或者服务器就是飞腾、鲲鹏、龙芯这一类的CPU上面要跑AI应用正好需要这套流程。这个项目做的事情就是在一台基于飞腾腾锐D3000的机器上从零开始搭建文心大模型的推理服务。不是调用云端接口而是把模型权重下载到本地通过推理框架加载起来对外提供接口让应用可以调用。这篇分享面向的是自己正在折腾或者计划折腾国产平台大模型部署的工程师尤其是搞信创适配、内网AI应用落地的朋友能少踩不少坑。1.2 方案选型为什么不是GPU也不直接调用API先说一个很多新手搞不清楚的认知问题。大家习惯了NVIDIA GPU上跑大模型到了飞腾D3000这种纯CPU、还未必有独立显卡的平台上第一反应往往是这能跑吗。实际上能跑只是速度和体量上有天花板。飞腾D3000没有CUDA生态你装不了CUDA、cuDNN也用不了PyTorch的GPU后端。但这个平台上可以用的方案并不少方案原理适合场景我的评价PaddlePaddle Paddle Inference百度自家框架对文心系列原生支持最好飞腾/鲲鹏等ARM平台、信创环境首选踩坑最少ONNX Runtime DNNL/OpenBLAS把模型导出为ONNXCPU推理需要跨框架迁移的情况可行但转换麻烦llama.cpp / Ollama量化GGUF模型CPU友好资源受限、追求轻量需要模型本身有GGUF版云端API不部署直接调用无数据合规要求的场景和部署无关不在讨论范围没有选择云端API原因很直白很多内网环境根本出不了网数据也不能出域。要解决的就是模型必须在本地跑这件事。没有选择llama.cpp作为主方案是因为文心系列在飞腾平台的社区优化主要是基于Paddle生态展开的用官方框架配合官方推理引擎兼容性和性能都更有保障。llama.cpp后续可以作为性能对比的备选方案去尝试但主推理链路我建议固定在Paddle上。还有一个容易忽略的选型细节是操作系统。飞腾D3000的开发板自带固件通常对银河麒麟V10适配最好UOS也可以但需要额外装内核头文件。我这次用的是银河麒麟V10 SP1内核版本5.10以上ARM64架构。如果你手上是其他发行版比如Ubuntu或者Debian只要内核支持ARMv8指令集流程基本一致差别只在软件包的安装命令上。1.3 硬件配置与性能预期管理先管理好预期CPU推理大模型速度不会像GPU那么快。飞腾D3000即使多核并发跑一个7B参数量的量化模型单次生成速度通常也就是每秒几个token到十几个token的量级约等于人阅读速度的三分之一到一半。但这不代表没有实用价值很多场景比如文档分类、关键词抽取、结构化信息整理对响应速度的敏感度没那么高几百毫秒到几秒的等待完全可以接受。我的硬件配置供参考处理器飞腾腾锐D30008核心ARMv8.2指令集内存64GB DDR4 ECC大模型推理对内存容量非常敏感建议至少32GB起步硬盘512GB NVMe SSD模型文件体积大IO快慢影响加载速度操作系统银河麒麟V10 SP1ARM64这里要强调内存的算法。以7B参数量的模型为例FP16精度下权重文件约14GB推理过程中还需要KV Cache和激活值的内存开销通常需要模型权重体积的1.5倍才能跑得舒服。也就是说14GB权重的模型16GB内存的机器就基本到极限了。如果想跑更大的模型要么上64GB内存要么对模型做量化压缩到INT8甚至INT4。我自己测下来的经验是同样一个7B模型INT8量化后权重约7GB内存占用大幅下降速度还有小幅提升效果损失基本可控。2. 飞腾ARM平台部署文心大模型的关键前置准备2.1 操作系统基础环境检查拿到机器后不要急着装东西先把底子摸清楚。我习惯按下面这个顺序做一轮检查每一个命令都有它要回答的具体问题。# 确认CPU架构 uname -m # 输出应该是 aarch64 或 arm64 # 确认内核版本最好5.10以上 uname -r # 确认操作系统发行版 cat /etc/os-release # 检查内存和交换分区 free -h如果uname -m输出的不是aarch64那基本可以断定你拿到的不是ARM版系统镜像后面装的软件包会各种不兼容。内核版本太低的话部分向量指令集特性无法启用Paddle的Kernel优化模块可能直接拒绝加载。内存检查这里有个实操技巧。第一次部署时我不小心在只有16GB内存的机器上试图加载7B模型结果加载到一半进程就被OOM Killer杀掉了日志里连个报错都没留下只有Killed三个字母。所以强烈建议部署前先确认内存充足或者预先把交换分区加大。虽然交换分区对推理性能没有帮助但至少能避免进程在加载阶段被直接干掉。2.2 ARM架构下的Python环境搭建飞腾平台上的Python环境有它的特殊性。不要直接用系统自带的Python 3.6或者3.7太老部分新版依赖库已经不再支持。也不要盲目下载x86的安装包架构不对装不上。我测试下来Python 3.10是比较稳妥的选择。# 安装编译工具链后面有依赖包需要现场编译 sudo apt update sudo apt install -y gcc g gfortran make cmake # 安装Python 3.10如果系统默认版本不是3.10 sudo apt install -y python3.10 python3.10-dev python3.10-venv # 创建虚拟环境避免污染系统Python python3.10 -m venv wenzhang_env source wenzhang_env/bin/activate # 升级pip和基础工具 pip install --upgrade pip setuptools wheel虚拟环境这一步强烈建议不要跳过。部署大模型过程中会装大量依赖包不同项目之间的版本冲突非常常见。我见过有同事图省事直接装在系统Python里后面跑另一个项目时发现numpy版本冲突系统里一堆服务起不来苦不堪言。2.3 飞腾平台PaddlePaddle安装技巧文心大模型在飞腾上的部署目前最顺滑的路径是PaddlePaddle框架。但PaddlePaddle的官方安装命令默认是基于x86架构写的直接跑会下载到不匹配的安装包。必须在安装时通过--platform参数指定ARM64版本。# 验证当前Python平台信息 python -c import platform; print(platform.platform()) # 确认显示的是 aarch64 / Linux # 在虚拟环境中安装ARM64版PaddlePaddle pip install paddlepaddle2.6.1 --platform manylinux2014_aarch64 --only-binary:all: --no-deps为什么用--no-deps因为ARM架构下部分依赖包如果让pip自动解析它会尝试去下载x86的编译版本直接安装失败。正确的做法是手动安装依赖然后再装Paddle本体。# 先手动安装numpy、protobuf这些核心依赖 pip install numpy1.24.4 protobuf3.20.3 # 再安装paddlepaddle此时不解析依赖 pip install paddlepaddle2.6.1 --platform manylinux2014_aarch64 --only-binary:all: --no-deps # 安装完成后验证 python -c import paddle; paddle.utils.run_check()补充常见的安装依赖包列表依赖包版本建议说明numpy1.24.4太新版本的numpy在部分ARM平台上会触发GLIBC不兼容protobuf3.20.3版本过高会与paddle内部通信模块冲突onnxruntime1.16.3如果走ONNX路线这个版本对ARM支持较完善openblas0.3.21需要从源码编译Paddle的CPU算子底层依赖libstdc随gcc 9以上系统自带老版本gcc会导致加载so库时符号找不到注意PaddlePaddle在飞腾平台上的安装包体积约150MB左右下载速度取决于网络环境。建议提前准备好离线安装包或者在网络状况好的时段操作。我在内网环境下用了本地代理仓库才解决下载问题。2.4 模型权重文件获取与格式确认文心大模型的权重文件可以从百度开源的渠道获取。当前比较常见的开源版本是ERNIE系列参数规模有不同的档位。部署前一定要确认清楚拿到的权重格式Paddle格式通常是一个model.pdmodel文件和若干个model.pdiparams文件直接用Paddle Inference加载。HuggingFace格式包含config.json、pytorch_model.bin等文件需要先做转换再给Paddle加载。GGUF格式供llama.cpp/Ollama使用CPU推理友好但文心系模型的GGUF转换工作要看社区是否已经有人完成。# 假设已下载Paddle格式权重到models/目录目录结构如下 models/ ├── ernie_3.0_tiny_chinese/ │ ├── model.pdmodel │ ├── model.pdiparams │ └── tokenizer.json如果拿到的是PyTorch权重需要先用PaddlePaddle的模型转换工具转成Paddle格式。这个过程不难但有几个细节容易出错比如embedding层和layernorm层的参数名称映射、position_ids的形状差异。我当时的做法是参考官方转换脚本把一个中文文本分类模型从HuggingFace格式转成了Paddle格式在飞腾上跑通后才决定把对话生成模型也走同样的路线。经验在国产平台上做模型部署格式转换往往是最大的时间黑洞。强烈建议优先找官方提供的Paddle格式权重省掉这一步。如果非要转换就用Docker启动一个x86机器来做转换再拷贝到飞腾上比在ARM上现场转换快得多。3. 手把手实操在飞腾D3000上把文心大模型跑起来3.1 部署管理服务与推理API搭建如果你之前了解过Dify、Ollama这类部署管理工具会发现它们简化了模型服务的启动过程。在飞腾平台上也有类似思路用一个轻量级的API服务把模型包起来调用方不关心底层推理细节只需要发HTTP请求即可。这里我用Paddle Serving作为推理服务层它是Paddle生态自带的模型服务化组件支持RESTful API也可以直接和Paddle Inference配套使用。在飞腾上安装pip install paddle-serving-server0.9.0 --platform manylinux2014_aarch64 --only-binary:all: --no-deps安装完成后写一个简单的服务端启动脚本# serve_ernie.py from paddle_serving_server import ServingServer from paddle_serving_client import Client # 配置模型路径和推理参数 model_config { model_path: models/ernie_3.0_tiny_chinese, port: 8080, device: cpu, max_body_size: 64 * 1024 * 1024 } # 启动服务 server ServingServer() server.set_model_config(model_config) server.start()# 启动服务 python serve_ernie.py启动日志里如果看到Server started successfully就说明服务已经就绪。3.2 模型加载与推理验证服务起来后先用一个最小化的测试脚本验证模型能不能正常推理# test_infer.py import json import urllib.request url http://127.0.0.1:8080/ernie/predict payload { text: 飞腾D3000是一款什么架构的处理器, max_length: 128, temperature: 0.7 } req urllib.request.Request( url, datajson.dumps(payload).encode(utf-8), headers{Content-Type: application/json} ) with urllib.request.urlopen(req) as resp: result json.loads(resp.read().decode(utf-8)) print(result[result])正常情况下的输出是一段中文文本。如果报错通常集中在两个地方模型路径错误报Model not found检查路径是否写对、权限是否可读。Kernel不匹配报No operator found或Operator ... is not implemented说明PaddlePaddle的ARM算子库没有涵盖这个模型中的某些算子通常是版本不匹配升级Paddle版本即可。跑通一次推理后建议用time命令统计一下耗时。比如time python test_infer.py如果响应时间在几秒内这个规模对于内部工具类应用完全可以接受。如果想要更稳定的秒级返回可以把模型切成INT8或者使用更小的模型。比如用ERNIE 3.0 Tiny大概0.5B参数量飞腾D3000上单次推理大约能控制在几百毫秒到一秒左右。3.3 量化与推理加速榨干CPU性能CPU推理要提速核心不外乎两点量化压缩模型体积、开启ARM平台的计算库优化。逐个说。模型量化从FP32到INT8通常可以把模型体积缩小到原来的1/4推理速度提升1.5到3倍不等效果损失在可接受范围内。Paddle提供了量化工具可以直接在部署时做在线量化# 安装量化工具 pip install paddle-quantization # 运行量化脚本输入模型路径输出量化后模型 python -m paddle_quantization.quantize \ --model_dir models/ernie_3.0_tiny_chinese \ --output_dir models/ernie_3.0_tiny_chinese_int8 \ --quant_type post_training \ --batch_size 8开启ARM优化编译PaddlePaddle时如果指定了-DWITH_ARMON推理时会自动使用NEON指令集加速。另一个关键是OpenBLAS。飞腾的CPU上有自己的向量指令集实现OpenBLAS针对ARM平台做了深度优化在矩阵乘法上有明显优势。如果安装时没有用OpenBLAS推理时每条样本的延迟可能会差到3到5倍。验证是否真的用上了OpenBLASpython -c from paddle.base import core; print(core.get_build_version())如果返回的输出中包含OpenBLAS字样说明已经启用。实际操作中我还调整了Paddle Inference的线程数。飞腾D3000是8核心默认线程数可能是4。用满8线程通常能带来额外20%-30%的吞吐提升import paddle import paddle.inference as paddle_infer config paddle_infer.Config(model.pdmodel, model.pdiparams) config.enable_mkldnn() config.set_cpu_math_library_num_threads(8) config.disable_gpu() predictor paddle_infer.create_predictor(config) predictor.run()这里的enable_mkldnn()是开启Intel MKL-DNN优化。对ARM平台它不一定生效但我实测在飞腾上开启它后部分算子会自动切换到Paddle自己的ARM实现兼容性没问题性能略有浮动。如果你担心不兼容可以不加这一行。3.4 彻底离线建立本地模型仓库前面所有操作都建立在能联网下载依赖包的前提下。但实际部署环境经常是完全离线内网。这时候需要一个本地依赖仓库把Paddle、numpy、protobuf、模型权重文件全部放进去然后用pip的--find-links参数从本地安装。创建目录结构建议offline_repo/ ├── wheels/ │ ├── paddlepaddle-2.6.1-cp310-cp310-linux_aarch64.whl │ ├── numpy-1.24.4-cp310-cp310-linux_aarch64.whl │ └── ... ├── models/ │ └── ernie_3.0_tiny_chinese/ └── install.shinstall.sh里可以写一个循环#!/bin/bash pip install --no-index --find-linkswheels/ wheels/*.whl这样在断网环境中也能实现一键安装。模型权重文件直接拷贝过去不需要走git lfs。注意离线部署的一个常见坑是Paddle框架依赖系统的libgomp、libstdc库这些属于系统级依赖pip不管。如果内网机器连这些库都没有需要预先装好gcc-gfortran或者对应的runtime包否则启动时会提示GLIBCXX_3.4.29 not found。4. 部署过程中的典型问题与性能调优4.1 问题排查速查表部署过程我踩了不少坑把典型的整理成下面这个表方便大家直接对照排查。问题现象可能原因解决方法Illegal instruction (core dumped)CPU指令集不兼容某个库针对更新指令集编译查看cat /proc/cpuinfo确认支持的指令集重装对应版本库或换低版本GLIBCXX_3.4.29 not found系统libstdc库太老sudo apt install libstdc6升级或手动拷贝新版库到/usr/lib/aarch64-linux-gnu/加载模型时Killed内存不足被OOM Killer杀掉增加交换分区sudo fallocate -l 16G /swapfile或用INT8量化模型No operator foundPaddle版本不识别该模型中的某些算子升级PaddlePaddle到更高版本确保算子库覆盖启动服务端口占用8080端口被其他进程占用lsof -i:8080查看到占用进程改端口或杀进程Cannot load library: libopenblas.so.0OpenBLAS未装或路径不对find / -name libopenblas*查找路径设置LD_LIBRARY_PATH中文乱码或输出空白tokenizer文件缺失或编码问题确认tokenizer.json在模型目录下UTF-8编码正常4.2 从能跑到跑得更好的调优记录很多人在CPU平台部署大模型试验跑通了就认为任务完成。但实际用起来会发现能跑和能满足业务需求之间还有距离。我从几个维度做了优化效果明显。第一轮优化启动加载时间未优化前每次启动模型服务需要加载权重文件7B FP16的模型加载大约要30-60秒。这个时间对于服务的一次性启动可以接受但如果频繁重启模型服务体验就很差。我的处理方式是把模型加载放到常驻内存作为一个常驻进程管理配合systemd设置服务自启避免反复加载。第二轮优化请求排队机制CPU推理速度有限如果同时来多个请求不加以控制就会互相争抢资源导致每个请求都变得很慢。Paddle Serving本身支持设置最大并发数可以把同一时间处理的请求数限制在2个其余请求排队等待。这样单请求延迟更稳定系统整体吞吐也更可控。# serving_config.yml worker_num: 2 max_body_size: 67108864 batching_enable: true max_batch_size: 8开启batching_enable之后多个短请求可以在同一个batch里执行CPU核心利用率明显提高。这个改动对文档批量处理类场景提升最大单个请求的在线对话场景收益有限。第三轮优化精度与速度的折中同一个7B模型FP32、FP16、INT8、INT4四种精度下速度和内存占用差异很大。我在飞腾上分别做了测试精度权重大小相对速度内存占用效果损失FP3228GB1x最慢很高无FP1614GB1.3x较高几乎无INT87GB2x中较小可接受INT43.5GB2.5x低有可感知的退化我的建议是业务场景对生成质量要求高、机器内存充足用FP16资源紧张、追求响应速度用INT8。INT4虽然可以在8GB内存的机器上跑7B模型但中文场景下生成质量下降比较明显除非万不得已不推荐。4.3 扩展阅读从单机推理到服务化上线如果你做的项目不止是个人实验而是要把模型能力接入业务系统那还需要考虑几个额外的东西。一是API接口的鉴权。直接裸奔的模型服务放在内网里一旦网络环境稍有暴露就很危险。至少加一个简单的Token鉴权可以在Nginx层做也可以在服务代码里做一个中间件拦截实现成本都很低。二是监控。模型服务运行期间需要关注请求量、响应时间、错误率、CPU和内存占用。飞腾D3000上的部署我通常配合Prometheus Grafana来监控相关的exporter可以直接跑在这个平台上面。监控做好后可以设置告警规则比如CPU跑到90%以上持续5分钟或者响应时间超过10秒就触发通知。这样可以尽早发现问题而不是等业务方来投诉。三是模型版本管理。如果之后要换新版本模型建议把版本号放进模型目录名里而不是直接覆盖同名文件方便回滚。5. 写在最后这篇文章我尽量把飞腾腾锐D3000上部署文心大模型的全过程拆开来讲但真正动手做和看文章是两回事。你部署过程中会遇到各种各样预想不到的问题有的是系统库版本不对有的是模型转换链路卡住还有的是性能远远达不到预期。这些都很正常也是这类项目的乐趣所在。就我个人的体会来说从x86平台迁移到ARM平台最大的一个感受是很多图上画着容易的步骤实际做起来要复杂得多。比如PaddlePaddle在飞腾上安装官方文档里有现成命令但直接复制粘贴大概率会报错因为平台的架构和依赖版本都会影响安装结果。真正要保证部署顺利还是得靠自己在虚拟环境里逐一把依赖理清耐心建好离线仓库这样后续无论是换机器还是扩展模型都有了一套可复制的方法。另外在CPU平台上跑大模型务必事先控制好预期。不可能指望着跑出GPU那样的速度但对于内部工具型应用来说秒级返回已经完全够用。如果后续你们有更高的性能要求也有两条路可以探索一是通过模型蒸馏、剪枝缩小模型规模二是如果业务允许把推理任务切分到多台飞腾机器上做分布式。分布式那条路复杂度高不少但在企业场景里往往是最终方向。最后再分享一个小技巧部署完成后记得把模型推理进程注册成systemd服务设置开机自启这样断电重启之后模型服务能自动恢复不用每次都到机器前面敲命令。在国产平台上做开发很多不起眼的细节攒多了就成了经验也希望这篇能帮你在自己的部署之路上少走几段弯路。
返回列表