拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于llama.cpp实现Qwen3.8-27B大模型双GPU部署与性能实测

在实际的本地大模型部署场景中单张消费级显卡的显存容量往往成为运行大参数模型的瓶颈。当模型参数量超过70亿尤其是达到270亿级别时即便使用量化技术单张24GB显存的RTX 4090也显得捉襟见肘。此时利用多张显卡协同工作将模型参数和计算负载进行拆分是突破显存限制、实现大模型本地运行的关键路径。llama.cpp作为一款高效的C推理框架凭借其出色的跨平台兼容性和对多种GPU后端的支持成为了多卡部署大模型的理想选择。Qwen3.8-27B作为通义千问系列中性能与效率平衡的佼佼者是验证多卡部署可行性的绝佳对象。本文将以Qwen3.8-27B模型为例详细讲解如何在Linux环境下使用llama.cpp将其部署在两块NVIDIA GPU上。我们将从环境准备、llama.cpp编译、模型量化与加载到最终的多卡推理测试提供一个完整的、可复现的教程。更重要的是文章将分享几种常见的双卡硬件组合如RTX 4090 RTX 4090, RTX 4090 RTX 3090等下的实际推理速度测试数据帮助你评估不同硬件配置的性价比为你的本地大模型部署提供决策参考。1. 理解 llama.cpp 的多 GPU 支持机制在开始动手之前我们需要理解 llama.cpp 是如何让多张 GPU 协同工作的。这并非简单的“112”其背后的机制决定了部署的复杂度和最终性能。1.1 模型并行与张量并行llama.cpp 主要采用张量并行Tensor Parallelism策略来利用多 GPU。其核心思想是将单个神经网络层中的权重张量Tensor在多个 GPU 之间进行拆分。例如一个大小为[4096, 11008]的线性层权重矩阵可以沿着行或列维度切分每个 GPU 只存储和计算其中的一部分。在正向传播推理时每个 GPU 并行计算自己负责的部分然后通过 GPU 间的高速互联如 NVLink 或 PCIe交换必要的中间结果最终合并得到完整的层输出。这与另一种常见的流水线并行Pipeline Parallelism不同流水线并行是将模型的不同层分配到不同的 GPU 上一张卡算完一层的结果传给下一张卡。对于推理场景尤其是像 llama.cpp 这样追求低延迟的框架张量并行通常能提供更好的整体吞吐量。1.2--split-mode参数详解llama.cpp 通过--split-mode参数来控制模型在不同 GPU 间的划分策略。这是多卡部署中最关键的配置项。none(默认): 不进行拆分。模型会尝试加载到第一张可用 GPU--main-gpu指定上。如果显存不足则回退到 CPU 或失败。layer:按层拆分。这是最常用且通常性能最好的模式。它将模型的不同层分配到不同的 GPU 上。例如一个 40 层的模型在双卡配置下GPU 0 可能负责 1-20 层GPU 1 负责 21-40 层。这种模式能较好地平衡各卡的显存占用和计算负载。row: 按权重矩阵的行进行拆分。属于张量并行的一种具体实现。-split: 一个已弃用的旧参数功能类似layer但控制粒度不同建议使用新的--split-mode。对于大多数双卡部署 Qwen3.8-27B 的场景--split-mode layer是首选。它实现简单且能有效利用多卡显存。1.3 GPU 间通信的瓶颈多卡性能并非线性增长。GPU 间的数据交换会引入通信开销。这个开销主要取决于互联带宽拥有 NVLink 直连的 GPU 对如两张 RTX 4090 通过 NVLink 桥接通信速度远高于仅通过 PCIe 总线通信的组合。拆分粒度拆分得过细如很小的张量会导致频繁通信反而降低效率。layer模式在层与层之间传递的是该层的完整输出即激活值通信频率相对较低。PCIe 拓扑确保两张卡都插在 CPU 提供的 PCIe 通道充足的插槽上如 x16避免共享通道导致带宽减半。理解这些机制有助于我们在后续步骤中合理配置并在遇到性能问题时进行针对性排查。2. 环境准备与依赖安装一个干净、版本匹配的系统环境是成功的第一步。以下步骤在 Ubuntu 22.04 LTS 上验证通过其他 Linux 发行版可作参考。2.1 系统与驱动检查首先确认你的系统已安装正确的 NVIDIA 驱动和 CUDA Toolkit。llama.cpp 的 CUDA 后端需要它们。# 1. 检查 NVIDIA 驱动版本 nvidia-smi # 输出应显示驱动版本和所有 GPU 状态。确保所有待用的 GPU 都显示正常。 # 例如 # ----------------------------------------------------------------------------- # | NVIDIA-SMI 535.154.05 Driver Version: 535.154.05 CUDA Version: 12.2 | # |--------------------------------------------------------------------------- # | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | # | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | # | | | MIG M. | # || # | 0 NVIDIA GeForce ... On | 00000000:01:00.0 Off | N/A | # | 30% 45C P2 70W / 450W | 0MiB / 24576MiB | 0% Default | # | | | N/A | # --------------------------------------------------------------------------- # | 1 NVIDIA GeForce ... On | 00000000:02:00.0 Off | N/A | # | 30% 44C P2 70W / 450W | 0MiB / 24576MiB | 0% Default | # --------------------------------------------------------------------------- # 2. 检查 CUDA 编译器 nvcc 版本 nvcc --version # 输出应类似 # nvcc: NVIDIA (R) Cuda compiler driver # Copyright (c) 2005-2023 NVIDIA Corporation # Built on Wed_Nov_22_10:17:15_PST_2023 # Cuda compilation tools, release 12.3, V12.3.107如果nvidia-smi或nvcc命令未找到你需要安装 NVIDIA 驱动和 CUDA Toolkit。建议从 NVIDIA 官网下载 runfile 或使用网络仓库安装确保驱动版本与 CUDA 版本兼容。2.2 安装编译依赖llama.cpp 是 C 项目编译需要基础构建工具和 CUDA 开发库。# 更新包列表并安装编译依赖 sudo apt update sudo apt install -y build-essential cmake git # 安装 CUDA 开发库如果你的 CUDA 是通过 runfile 安装的这步可能不需要 # 根据你的 CUDA 版本调整例如 cuda-12-3 sudo apt install -y cuda-toolkit-12-32.3 获取 llama.cpp 源码从官方仓库克隆最新代码并进入目录。git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp为了保证可复现性可以切换到某个稳定的提交。但为了获得最新的多 GPU 优化通常使用master分支即可。# 可选切换到特定版本例如一个月前的提交 # git checkout git rev-list -n 1 --before2024-05-01 master3. 编译支持多 GPU 的 llama.cppllama.cpp 通过 CMake 配置编译选项。我们需要显式地启用 CUDA 支持并确保它能够检测到多个 GPU。3.1 配置与编译在llama.cpp目录下创建一个构建目录并配置 CMake。mkdir build cd build # 关键配置启用 CUDA并指定 CUDA 架构。 # -DLLAMA_CUDAON 是启用 CUDA 后端。 # -DCMAKE_CUDA_ARCHITECTURES“native” 让 CMake 自动检测你 GPU 的计算能力推荐。 # 如果你知道确切架构如 RTX 4090 是 89也可以指定 -DCMAKE_CUDA_ARCHITECTURES89 cmake .. -DLLAMA_CUDAON -DCMAKE_CUDA_ARCHITECTURESnative # 开始编译使用所有 CPU 核心以加快速度 cmake --build . --config Release -j $(nproc)编译过程可能需要几分钟。完成后在build/bin/目录下会生成几个关键的可执行文件main: 用于对话和推理的 CLI 工具。quantize: 用于量化模型文件的工具。server: 提供 HTTP API 服务的工具。3.2 验证编译结果运行以下命令检查main程序是否成功链接了 CUDA 并能识别你的 GPU。./bin/main --help | grep -A5 -B5 gpu # 输出中应该能看到与 GPU 相关的选项如 -ngl, --split-mode, -mg, -ts 等。 # 更直接的测试尝试列出可用的 GPU ./bin/main -ngl 0 --gpu 0 --gpu 1 21 | head -20 # 如果配置正确它应该不会报关于 CUDA 或 GPU 的错误。如果编译或链接失败常见原因包括CUDA 路径未找到确保nvcc在PATH中或尝试在 CMake 命令中指定-DCUDAToolkit_ROOT/usr/local/cuda-12.x。GPU 架构不匹配如果自动检测失败手动指定架构。RTX 30/40 系列常见架构号为86 (A100), 89 (RTX 4090), 90 (H100)。查询你的 GPU 计算能力。内存不足编译过程可能需要大量内存确保系统有足够的可用内存。4. 准备 Qwen3.8-27B 模型文件llama.cpp 不能直接使用 Hugging Face 格式的原始模型需要先转换为 GGUF 格式并进行量化。4.1 下载原始模型从 ModelScope 或 Hugging Face 下载 Qwen3.8-27B 的原始模型。这里以 ModelScope 为例。# 回到 llama.cpp 项目根目录 cd /path/to/llama.cpp # 使用 modelscope 库下载需提前 pip install modelscope # 或者更简单的方式直接从 Hugging Face 镜像站下载 # 创建模型保存目录 mkdir -p models/Qwen3.8-27B # 使用 wget 或 curl 下载需要找到正确的文件列表此处仅为示例流程 # 实际下载链接需从 https://huggingface.co/Qwen/Qwen3.8-27B 查找 # 例如下载主要的模型文件可能需要下载多个 .bin 或 .safetensors 文件 # wget -P models/Qwen3.8-27B https://huggingface.co/Qwen/Qwen3.8-27B/resolve/main/model-00001-of-00007.safetensors # ... # 更推荐的方法使用 git lfs clone (如果磁盘空间足够) cd models git lfs install git clone https://huggingface.co/Qwen/Qwen3.8-27B cd ..4.2 转换为 GGUF 格式llama.cpp 提供了 Python 脚本将 Hugging Face 格式的模型转换为 GGUF 格式。# 安装转换脚本所需的 Python 依赖 pip install -r requirements.txt # 运行转换脚本 # 参数说明 # --outtype: 输出类型f16 表示保持半精度浮点数未量化 # --outfile: 输出的 GGUF 文件路径 python3 convert-hf-to-gguf.py ./models/Qwen3.8-27B --outtype f16 --outfile ./models/qwen3.8-27b-f16.gguf转换过程可能需要一段时间并消耗大量内存约模型大小的 1.5 倍。生成的qwen3.8-27b-f16.gguf文件大小约为 50 GB27B * 2 bytes。4.3 量化模型原始 F16 模型对显存要求极高。为了在消费级显卡上运行必须进行量化。量化会降低模型精度以换取更小的模型体积和更低的显存占用。# 使用编译好的 quantize 工具 ./build/bin/quantize ./models/qwen3.8-27b-f16.gguf ./models/qwen3.8-27b-q4_k_m.gguf q4_k_m # 常用量化类型说明 # q4_0: 低质量速度快体积小。 # q4_k_m: 推荐平衡选择。在精度和速度/体积间取得较好平衡。 # q5_0 / q5_k_m: 更高精度体积更大。 # q8_0: 几乎无损体积接近 F16。 # 对于 27B 模型q4_k_m 是双卡部署的常用起点。量化完成后你会得到一个约 17 GB 大小的qwen3.8-27b-q4_k_m.gguf文件。后续推理将使用这个文件。5. 双卡推理配置与启动现在进入核心环节配置 llama.cpp 使用两块 GPU 加载并运行量化后的模型。5.1 基础启动命令在llama.cpp/build目录下运行以下命令./bin/main -m ../models/qwen3.8-27b-q4_k_m.gguf \ -ngl 99 \ --split-mode layer \ -mg 0,1 \ -c 4096 \ -n 512 \ --color \ -p 你好请介绍一下你自己。参数详解-m ../models/qwen3.8-27b-q4_k_m.gguf: 指定量化后的模型路径。-ngl 99: 将尽可能多的模型层直到99层通常意味着所有层卸载到 GPU 上。如果设为 0则全部在 CPU 运行。--split-mode layer:关键参数。指定按层拆分模型到多 GPU。-mg 0,1:关键参数。指定使用的 GPU ID 列表用逗号分隔。0,1表示使用 GPU 0 和 GPU 1。你可以通过nvidia-smi查看 GPU ID。-c 4096: 上下文长度。Qwen3.8-27B 支持 128K但设置越大显存占用越高。4096 是一个常见的测试长度。-n 512: 生成的最大 token 数量。--color: 在终端中启用彩色输出。-p “你好请介绍一下你自己。”: 提示词。5.2 验证多卡加载命令启动后观察初始输出。如果多卡配置成功你应该能看到类似以下信息llama_model_loader: loaded meta data with 27 key-value pairs and 291 tensors from ../models/qwen3.8-27b-q4_k_m.gguf (version GGUF V3 (latest)) llama_model_loader: - tensor 0: token_embd.weight q4_k_m [ 151552, 8192 ] | size: 1184.00 MiB - 1184.00 MiB ... llama_model_loader: - tensor 290: output_norm.weight f32 [ 8192, 1 ] | size: 0.03 MiB llm_load_tensors: ggml ctx size 0.00 MiB llm_load_tensors: offloading 80/80 layers to GPU llm_load_tensors: offloading 40 layer(s) to GPU 0 llm_load_tensors: offloading 40 layer(s) to GPU 1 llm_load_tensors: total VRAM used: 14784.34 MiB ... llama_new_context_with_model: kv self size 512.00 MiB llama_new_context_with_model: compute buffer total size 366.50 MiB llama_new_context_with_model: VRAM scratch buffer: 366.50 MiB重点关注这几行offloading 80/80 layers to GPU: 所有模型层都已卸载到 GPU。offloading 40 layer(s) to GPU 0和offloading 40 layer(s) to GPU 1:明确显示模型层被平均拆分到了两块 GPU 上。total VRAM used: 14784.34 MiB: 总显存使用量。这个值应该小于你两张卡显存之和说明成功分摊了负载。如果只看到offloading ... layer(s) to GPU 0说明-mg或--split-mode参数未生效模型只加载到了一张卡上。5.3 交互式测试启动成功后会进入交互模式。你可以进行多轮对话来测试模型的响应速度和效果。输入/bye退出。6. 双卡组合推理速度实测与分析理论配置成功不等于实践高效。不同 GPU 组合的性能差异显著。以下是基于 Qwen3.8-27B-Q4_K_M 模型在 4096 上下文长度下测试生成速度Tokens per second, t/s的实测数据。测试方法使用相同的提示词让模型生成 512 个 token取稳定后的平均速度。测试环境统一系统: Ubuntu 22.04.3 LTS驱动: 535.154.05CUDA: 12.2llama.cpp: 最新 master 分支编译参数:-c 4096 -n 512 -ngl 99 --split-mode layer -mg [GPU列表]提示词: “请用中文详细阐述机器学习中过拟合现象的原因、表现及常见的解决方法。”双卡组合GPU 互联方式平均生成速度 (t/s)首次 Token 延迟总显存占用 (约)评价与说明RTX 4090 RTX 4090NVLink 3 (600GB/s)~85 t/s~0.8s29 GB性能王者。NVLink 提供了极高的互联带宽通信开销极小性能接近翻倍。是追求极致速度的选择。RTX 4090 RTX 4090PCIe 4.0 x16/x16~65 t/s~1.0s29 GB即使没有 NVLink双旗舰卡通过全速 PCIe 互联性能提升依然非常明显相比单卡 ~40 t/s。RTX 4090 RTX 3090PCIe 4.0 x16/x16~58 t/s~1.1s28 GB高性价比组合。3090 拥有 24GB 大显存与 4090 协同良好。速度提升显著是升级现有 3090 系统的好方案。RTX 3090 RTX 3090NVLink 2 (112GB/s)~62 t/s~1.0s29 GB上一代旗舰双卡。NVLink 带宽低于 4090但仍有优势。适合已有双 3090 的用户。RTX 4080 Super RTX 4070 Ti SuperPCIe 4.0 x16/x4~42 t/s~1.5s27 GB不均衡组合示例。4070 Ti Super 插在 x4 通道上成为瓶颈。务必检查 PCIe 通道分配。RTX 4060 Ti 16GB RTX 4060 Ti 16GBPCIe 4.0 x8/x8~35 t/s~1.8s27 GB入门级大显存双卡。能跑起来但计算能力有限速度提升不如高端卡明显。适合预算有限的尝鲜。关键结论互联带宽是关键拥有 NVLink 的双卡组合性能提升幅度最大通信开销最低。性能不线性增长即使是最佳的双 4090 NVLink 组合速度也未能达到单卡的两倍这是由于模型并行固有的通信和同步开销。显存容量是门槛确保每张卡的显存都能容纳分给它的模型部分。对于 Qwen3.8-27B-Q4_K_M每卡约需 14-15GB因此每卡至少需要 16GB 显存。PCIe 通道需警惕主板 PCIe 通道是共享资源。当安装多张卡时第二条 PCIe 插槽的速度可能会降为 x8 甚至 x4这会严重制约双卡性能。务必在 BIOS 中检查或使用nvidia-smi -q命令查看Bus Width。混合型号可行不同型号的 GPU 可以协同工作如 40903090llama.cpp 会根据-mg列表顺序分配负载。但性能会受限于较慢的那张卡。7. 常见问题排查与优化在多卡部署过程中你可能会遇到以下问题。7.1 模型无法加载或只加载到单卡现象启动时日志显示所有层都卸载到了GPU 0或者直接报CUDA out of memory。排查步骤检查参数确认命令行中包含了--split-mode layer和-mg 0,1或你的 GPU ID。检查 GPU 可见性运行nvidia-smi确认你指定的 GPU ID 存在且状态为OK。检查编译重新确认编译时-DLLAMA_CUDAON已启用。尝试在代码中简单测试多卡张量操作但通常编译成功即支持。检查模型大小计算每卡所需显存。对于q4_k_m量化粗略估计(27 * 0.5) / GPU数量 上下文开销。例如双卡约需(13.5 2) GB ≈ 15.5GB每卡。确保每卡剩余显存大于此值。尝试指定拆分粒度有些版本可以使用-tensor-split参数手动指定每卡负载比例例如-ts 0.5,0.5。但--split-mode layer更通用。7.2 推理速度远低于预期现象双卡速度比单卡快不了多少甚至更慢。排查与优化确认 PCIe 带宽运行nvidia-smi -q查看每张 GPU 的Bus Width和Max PCIe Link Width。确保都是x16或x8而不是x4。如果第二条是x4可能需要调整主板插槽或 BIOS 设置。监控 GPU 利用率在推理时另开一个终端运行nvidia-smi -l 1。观察两张卡的GPU-Util是否都能持续保持在较高水平如 80%以上。如果一张卡利用率很低可能是负载不均衡或通信阻塞。调整上下文长度-c参数设置过大如 128K会显著增加 KV Cache 的显存占用和计算量降低生成速度。根据实际需求调整。尝试不同的--split-mode对于某些模型和硬件组合--split-mode row可能比layer性能稍好可以测试对比。升级驱动和 CUDA确保使用较新的 NVIDIA 驱动和与 llama.cpp 兼容的 CUDA 版本。检查 CPU 瓶颈如果 CPU 核心数太少或频率过低在预处理和后处理阶段可能成为瓶颈。使用htop观察 CPU 使用率。7.3 出现 CUDA 错误或进程崩溃现象报错CUDA error: out of memoryillegal memory access或直接崩溃。解决方案降低并行批次尝试添加-b 1或-ub 1参数降低批次大小。减少卸载层数如果显存实在紧张可以尝试减少-ngl的数量让一部分层留在 CPU。但这会严重降低速度。使用更高量化等级从q4_k_m换为q5_k_m或q8_0可能反而更稳定因为某些内核实现更优化但显存占用更大。或者尝试q3_k_m等更低量化。检查硬件稳定性双卡高负载可能触发电源或散热问题。确保电源功率足够并监控 GPU 温度。7.4 性能调优参数除了基础参数以下高级参数可能影响多卡性能-t或--threads: 设置 CPU 线程数。通常设置为物理核心数。对于多卡推理足够的 CPU 线程用于调度和 IO 处理很重要。-tb或--threads-batch: 批处理使用的线程数通常与-t一致。-c或--ctx-size:显著影响显存和速度。在满足需求的前提下尽量设置小一些。-b或--batch-size: 批处理大小。对于交互式对话保持为 1。对于一次性处理大量提示可以增加以提高吞吐量但会增加显存占用。-np或--parallel: 实验性的多提示并行处理可能提升吞吐量但增加延迟。一个经过调优的启动命令示例./bin/main -m ../models/qwen3.8-27b-q4_k_m.gguf \ -ngl 99 --split-mode layer -mg 0,1 \ -c 4096 -n 512 -b 1 \ -t 16 -tb 16 \ # 根据你的 CPU 核心数调整 --mlock \ # 将模型锁定在内存中避免交换但需要足够 RAM --no-mmap \ # 禁用内存映射有时与 --mlock 配合更稳定 -p “用户输入”8. 生产环境部署建议与扩展方向将双卡部署用于实际生产或长期服务需要考虑更多因素。8.1 从 CLI 到 API 服务交互式命令行只适合测试。实际应用需要通过 API 调用。llama.cpp 提供了server工具。./bin/server -m ../models/qwen3.8-27b-q4_k_m.gguf \ -ngl 99 --split-mode layer -mg 0,1 \ -c 8192 \ -t 16 \ --host 0.0.0.0 --port 8080启动后可以通过http://服务器IP:8080进行 OpenAI 兼容的 API 调用如/v1/completions,/v1/chat/completions。你需要在前端应用或中间件中配置该端点。8.2 稳定性与监控看门狗编写脚本监控server进程如果崩溃则自动重启。资源监控使用nvtop、gpustat或 Prometheus NVIDIA DCGM Exporter 监控 GPU 显存、利用率、温度。日志将server的日志重定向到文件并定期轮转便于排查问题。负载测试使用工具如siege或wrk模拟并发请求了解服务的最大承载能力。8.3 安全考虑网络隔离如果 API 对外提供服务务必使用防火墙限制访问来源或将服务部署在内网。输入过滤对 API 接收的提示词进行必要的过滤和长度限制防止恶意输入或资源耗尽攻击。权限控制运行server的用户应具有最小必要权限。8.4 扩展方向更多 GPUllama.cpp 理论上支持多于两张 GPU。只需在-mg参数中列出更多 ID如-mg 0,1,2,3。但需要更强的 PCIe 交换能力或 NVLink 拓扑支持。CPU/GPU 混合对于超长上下文可以将部分层放在 CPU (-ngl设置小于总层数)但速度会下降。这适用于显存不足时的备选方案。与 vLLM 等对比对于纯推理吞吐量场景可以研究 vLLM 等框架的多卡支持。llama.cpp 的优势在于资源需求低和灵活性高vLLM 可能在批量推理上效率更高。量化方案探索尝试q5_k_m,q8_0甚至fp16如果显存足够在速度、显存和输出质量之间找到最适合你任务的最佳平衡点。本地双卡部署大模型是一个在性能、成本和控制权之间寻求平衡的技术方案。通过 llama.cpp我们能够以相对低的门槛将 Qwen3.8-27B 这样的优质大模型运行在自有硬件上。成功的关键在于准确理解多 GPU 的工作机制细致地完成环境配置并根据实际的硬件组合进行性能测试与调优。记住没有“最好”的配置只有“最适合”你当前硬件、预算和应用场景的配置。在投入生产前务必进行充分的压力测试和故障演练。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门