ik_llama.cpp 老工作站多 GPU 部署 Qwen3-235B-A22B 实战指南:从 OOM 崩溃到稳定推理

发布时间:2026/9/18 3:06:17

ik_llama.cpp 老工作站多 GPU 部署 Qwen3-235B-A22B 实战指南:从 OOM 崩溃到稳定推理 ik_llama.cpp 老工作站多 GPU 部署 Qwen3-235B-A22B 实战指南从 OOM 崩溃到稳定推理【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp导读本文围绕 ik_llama.cpp 社区讨论 384 - ik_llama.cpp issues on an old workstation 中的真实排障案例展开讲述如何在 CPU 较老、显存有限2×2080Ti 11GB、64GB 内存、SSD 交换的工作站上通过-sm分裂模式、-ot张量覆写、-DGGML_SCHED_MAX_COPIES1重编译等组合手段让 Qwen3-235B-A22B 这类超大 MoE 模型跑起来。读完本文你将掌握多 GPU 下分裂模式的选择边界、-ot覆写规则的顺序语义、pipeline parallelism 拷贝数对显存的影响以及一套可复制的多 GPU 调优排查路径。背景一台 6 年旧工作站跑 235B MoE 模型的挑战讨论发起人matt23654的硬件配置是i9-9940X 处理器、64GB 四通道内存、两张 RTX 2080 Ti各约 11GB 显存、一块较新的高速 SSD。他成功加载了 ubergarm 发布的 Qwen3-235B-A22B GGUF 量化模型IQ3_K 混合量化、分片文件但一旦涉及多 GPU 协同就出现两个典型问题-sm layer默认分裂模式下加载阶段 CUDA 试图分配约 170GB 显存直接cudaMalloc failed: out of memory随后加载失败甚至 Segfault-sm row模式下把 MoE 专家权重固定到 CUDA1 会出现 illegal memory access不固定时则报GGML_ASSERT(!ggml_backend_buffer_is_cuda_split(src0_1-buffer) mul_mat_id does not support split buffers)。从日志可以看到崩溃发生在计算缓冲区compute buffers分配阶段llama_new_context_with_model: n_ctx 8192 llama_new_context_with_model: n_batch 2048 llama_new_context_with_model: n_ubatch 512 llama_new_context_with_model: flash_attn 1 llama_new_context_with_model: fused_moe 1 llama_kv_cache_init: CUDA0 KV buffer size 768.00 MiB llama_kv_cache_init: CUDA1 KV buffer size 736.00 MiB llama_new_context_with_model: pipeline parallelism enabled (n_copies4) ggml_backend_cuda_buffer_type_alloc_buffer: allocating 167771.94 MiB on device 0: cudaMalloc failed: out of memory ggml_gallocr_reserve_n: failed to allocate CUDA0 buffer of size 175921630208 llama_new_context_with_model: failed to allocate compute buffers关键线索在pipeline parallelism enabled (n_copies4)这一行它意味着调度器为流水线并行预分配了多份输入拷贝缓冲区直接放大了显存占用导致 11GB 的 2080 Ti 根本无法满足分配请求。分裂模式-sm的适用边界MoE 模型不要用 row四种分裂模式及其语义在 common/common.cpp 中-sm, --split-mode支持四种取值取值语义none仅使用单张 GPU配合-mg指定主卡layer默认按层切分层与 KV 缓存分布到多张 GPUattn注意力相关张量按指定方式切分分裂模式细分变体graph张量与计算图同时跨 GPU 切分ikawrakow 在讨论中明确表态Split mode row does not work for MoE models (and Im not sure if it works for dense models as I dont have access to a multi-GPU system, so have not tested since forking). Im pretty sure split mode row does not work for MoE models in mainlinellama.cppeither.也就是说row 分裂模式在 MoE 模型上不可用。这与报错信息相互印证mul_mat_id does not support split buffers。从实现层面看MoE 的专家路由expert routing计算依赖mul_mat_id这类算子而 split buffers张量按行切分到多设备与 3D 张量的组合在 llama.cpp 系实现中并不受支持——讨论中参与者 ubergarm 也指出这正是 split buffers 与 3D 张量组合的已知限制。因此在多 GPU 部署 MoE 模型时请直接放弃-sm row这条路径。layer 模式为什么也会炸出 170GB 分配同样是 layer 模式报错时日志中n_copies4是问题核心。ggml-backend.cpp 中定义了编译期宏#ifndef GGML_SCHED_MAX_COPIES #define GGML_SCHED_MAX_COPIES 1而在 ggml-backend.cpp 中调度器在并行场景下会按该宏决定流水线并行拷贝份数sched-n_copies parallel ? GGML_SCHED_MAX_COPIES : 1;默认构建时 ggml/CMakeLists.txt 将GGML_SCHED_MAX_COPIES缓存默认值设为1但如果你使用主线的其他预设或自行覆盖为4就会在日志中看到pipeline parallelism enabled (n_copies4)此时调度器会为每个后端维护GGML_SCHED_MAX_COPIES份事件与缓冲见 ggml-backend.cpp 的events[GGML_SCHED_MAX_BACKENDS][GGML_SCHED_MAX_COPIES]。对于 Qwen3-235B 这种体量的模型多份计算缓冲的预留量直接膨胀到百 GB 级远超 11GB 显存上限于是出现allocating 167771.94 MiB这类荒谬的分配请求。解决方案以-DGGML_SCHED_MAX_COPIES1重编译ubergarm 给出的核心建议是重编译时强制拷贝数为 1# 不使用 BLAS并设置 -DGGML_SCHED_MAX_COPIES1 cmake -B build -DGGML_CUDAON -DGGML_RPCOFF -DGGML_BLASOFF -DGGML_SCHED_MAX_COPIES1 cmake --build build --config Release -j $(nproc)讨论者的实测反馈是-DGGML_SCHED_MAX_COPIES1生效后不再尝试分配 170GB 显存模型成功加载并获得了约 15 tok/s 的 prompt processing 速度与约 6 tok/s 的生成速度。这一点也与 docs/build.md 中给出的 Windows 构建示例相互印证-DGGML_SCHED_MAX_COPIES1同时在社区讨论 100 - New argument / env variable for GGML_SCHED_MAX_COPIES 中作者也确认该编译期宏会显著影响显存占用与性能当前版本仅支持编译期配置尚未提供运行时参数或环境变量开关。张量覆写-otMoE 多 GPU 布署的核心工具-ot的解析机制-ot, --override-tensor的完整帮助文本见 common/common.cpp-ot, --override-tensor NAME override tensor buffer type as tensor_namebuft, comma-separated参数格式为张量名缓冲类型支持逗号分隔多个条目且可以多次指定。解析逻辑在 common/common.cpp 的parse_buft_overrides中它会枚举所有已注册后端ggml_backend_reg_get_count()将CUDA0、CUDA1、CPU等缓冲类型名映射到对应的 buffer type然后以张量名的正则模式与目标缓冲类型构成llama_model_tensor_buft_override结构体。模型加载时llama.cpp 会依据这些覆写逐张量匹配并重定向到指定设备同时注意手动张量覆写不能与--fit自动显存适配同时使用if (ml.tensor_buft_overrides) { throw std::runtime_error(Manual tensor overrides cannot be used with --fit); }覆写规则的顺序语义重要ikawrakow 在讨论中特别强调Note that the tensor overrides are processed in the order they were defined on the command line.这意味着命令行中先出现的-ot规则先匹配先生效已被前面规则“接管”的张量不会再次被后续规则命中因此顺序本身就是一种路由策略先精确固定希望留在 GPU 的层剩下的自然落入兜底规则如expsCPU。他的示例配置是针对两张相同 GPU 的起点-ngl 99 -ts 50,50 -ot blk\.[0-1]\.ffnCUDA0,blk\.[2-3]\.ffnCUDA1,expsCPU解析过程blk.[0-1].ffn相关张量先被固定到 CUDA0blk.[2-3].ffn固定到 CUDA1最后exps其余专家权重兜底到 CPU。由于前两条规则已经处理了要留在 GPU 的专家后续专家自然全部进入 CPU。关于 Qwen3 与 DeepSeek 命名差异的坑ubergarm 指出一个常见的踩坑点a lot of folks keep using-ot ^blk\.[3-9]\.ffn_.*_exps\.CPUwhich misses some other ffn layers without theexpsas the naming convention on Qwen3 is a bit different than DeepSeek for example.即Qwen3 的 ffn 层命名与 DeepSeek 不完全一致只匹配*_exps*会漏掉一部分不带exps后缀的 ffn 张量导致它们仍被留在 GPU 上。正确做法是用更宽泛的模式如ffn.*CPU显式覆盖全部 ffn。完整推荐命令ubergarm 方案build/bin/llama-server \ -m ~/.cache/huggingface/hub/models--ubergarm--Qwen3-235B-A22B-GGUF/snapshots/073738969f80d41f288cbfd6a29523769336bee8/Qwen3-235B-A22B-mix-IQ3_K-00001-of-00003.gguf \ -c 8192 \ -ctk q8_0 -ctv q8_0 \ -fa \ -fmoe \ -ngl 99 \ -ts 50,50 \ -ot blk\.(0|1)\.ffn.*CUDA0 \ -ot blk\.(2|3)\.ffn.*CUDA1 \ -ot ffn.*CPU \ -t 16 \ --temp 0.6 \ --top-k 20 \ --top-p 0.95 \ --min-p 0 \ --presence-penalty 1.5 \ -v \ --host 127.0.0.1 \ --port 4000该命令的要点-ctk q8_0 -ctv q8_0KV 缓存采用 q8_0 量化显著降低 KV 显存占用日志中默认 f16 KV 为 1504 MiB量化后更省-fa启用 Flash Attention降低中间激活与 KV 访问开销-fmoe启用融合 MoE 执行路径日志中fused_moe 1-ngl 99尽可能把所有层交给 GPU 调度实际由-ot精确控制去向-ts 50,50两张 GPU 各承担 50% 的按层切分比例-ts, --tensor-split语义见 common/common.cpp按,或/分割缺省位补 0三条-ot规则按顺序执行第 0/1 层 ffn 到 CUDA0第 2/3 层 ffn 到 CUDA1其余所有 ffn 兜底到 CPU-t 16线程数设为物理核心数i9-9940X 为 10 核 20 线程作者建议从 16 开始实验。如果显存还有余量例如每卡可用约 11GB可以逐层增加 GPU 上的 ffn 层数直到接近 OOM-ot blk\.(0|1|2)\.ffn.*CUDA0 \ -ot blk\.(3|4|5)\.ffn.*CUDA1 \为什么不用-rtr运行时重打包讨论中 ikawrakow 曾建议尝试-rtr, --run-time-repack看能否提升 prompt processing 速度其语义见 common/common.cpprepack tensors if interleaved variant is available。但 ubergarm 指出在 64GB 内存、235B 模型的场景下-rtr并不合适-rtr会禁用 mmap权重需要完整落内存对 64GB 内存几乎不可能容纳 235B 模型结论是建议放弃-rtr改用离线张量重打包offline tensor repack把未卸载到 GPU 的权重重打包为_R4变体既享受重打包后的性能收益又能继续使用 mmap 在 64GB 内存下运行。多 GPU 调优的通用方法论综合讨论中作者与参与者给出的建议可以提炼出一套可复用的调优流程确定分裂模式MoE 模型直接用默认的-sm layer可省略该参数不要使用-sm row确保流水线并行拷贝数为 1以-DGGML_SCHED_MAX_COPIES1重编译观察日志中出现pipeline parallelism enabled (n_copies1)即正常先粗后细用-ngl 99 -ot expsCPU -ts 50,50这类简单配置起步观察每张 GPU 的实际显存占用逐层精调利用-ot的顺序语义把希望留在 GPU 的层按序固定到 CUDA0/CUDA1其余 ffn 统一兜底到 CPU为系统“减负”使用量化 KV 缓存-ctk/-ctv、Flash Attention-fa、融合 MoE-fmoe做减法在显存紧张的老平台上关闭 BLAS-DGGML_BLASOFF反而可能更快——讨论者实测 OpenBLAS 编译后性能不升反降量入为出不要把全部专家都塞进 GPUSSD 交换 内核缓存专家访问不均匀时可以让 CPU 侧推理速度接近内存带宽上限正如讨论者的观察Qwen 未均匀选择专家内核缓存使生成速度更接近四通道内存速度。讨论者最终在 i9-9940X 64GB 2×2080 Ti 上获得约 15 tok/s PP、6 tok/s TG 的成绩并认为瓶颈主要在 SSD 带宽与老 CPU而作者也补充PP 仅为 TG 的 2.5 倍并不正常这类现象值得进一步排查例如 SSD 在 prompt 处理阶段的带宽争用。从源码看这些参数如何协作最后把本文涉及的关键参数在源码中的位置汇总方便继续深入参数/宏源码位置说明-sm, --split-modecommon/common.cpp四种分裂模式解析-ts, --tensor-splitcommon/common.cpp多 GPU 切分比例解析-ot, --override-tensorcommon/common.cpp、common/common.cpp张量覆写解析与帮助文本-rtr, --run-time-repackcommon/common.cpp运行时张量重打包开关GGML_SCHED_MAX_COPIESggml/CMakeLists.txt、ggml/src/ggml-backend.cpp、ggml/src/ggml-backend.cpp流水线并行拷贝数编译期手动覆写与--fit互斥src/llama.cpp覆写存在时禁止自动适配对于还想进一步压缩显存、提升性能的读者可以关注仓库中相关的社区讨论100 - New argument / env variable for GGML_SCHED_MAX_COPIES该宏对显存与性能影响的讨论258 - Quick-start Guide coming over from llama.cpp and ktransformers从主线迁移到 ik_llama.cpp 的多 GPU 综合指南。小结老工作站跑超大 MoE 模型并非不可能关键在于把“该在哪计算”这一决策显式化用-sm layer代替-sm row、用-DGGML_SCHED_MAX_COPIES1消除百 GB 级的流水线缓冲预留、用顺序化的-ot规则把专家权重精确路由到 GPU 或 CPU再辅以量化 KV、Flash Attention 与融合 MoE 选项。这套方法不仅适用于 Qwen3-235B-A22B对其他超大 MoE 量化模型的多 GPU 部署同样具有直接参考价值。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/18 3:06:17

基于 CANN hixl 仓库实践:用 GitCode API 高效读取与分析 Issue

基于 CANN hixl 仓库实践:用 GitCode API 高效读取与分析 Issue 【免费下载链接】hixl HIXL(Huawei Xfer Library)是一个灵活、高效的昇腾单边通信库,面向集群场景提供简单、可靠、高效的点对点数据传输能力。 项目地址: https:…

2026/9/18 3:06:17

零成本搭出完整创意工作流:免费开源 Adobe 替代品全指南

零成本搭出完整创意工作流:免费开源 Adobe 替代品全指南 【免费下载链接】Adobe-Alternatives A list of alternatives for Adobe software 项目地址: https://gitcode.com/GitHub_Trending/ad/Adobe-Alternatives 这篇指南写给所有在 Adobe 订阅续费页面前犹…

2026/9/18 3:01:17

无线麦克风与192kHz高采样率选型:闪克PD200W/PD300X对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/18 4:01:19

Linux命令拾遗-top中的%nice是啥

简介# 这是Linux命令拾遗系列的第八篇,本篇主要介绍top命令中nice%这个指标的含义以及进程优先级相关内容。 在各种查看CPU使用率的工具中(如top),一般都有us%、sy%、ni%等,us%与sy%含义是比较容易理解的,一个是用户态CPU使用率…

2026/9/18 4:01:19

大模型系统提示词泄露全解析:从原理到防御的实战指南

1. 先聊聊这个标题到底在说什么如果你最近在逛技术社区、刷 AI 相关的资讯,大概率会频繁撞见system_prompts_leaks这个关键词。它并不是某个具体项目的代号,而是指过去一年里在 LLM 应用领域掀起巨浪的一类现象:大语言模型的系统提示词&#…

2026/9/18 3:56:19

Excel数据批量转Word工具拆解与Python实现

最近有朋友把“Excel 数据批量转 Word 工具(2026年最新版)”分享到群里,说是在国内一个软件分享社区看到的大神作品。我研究了一下这个工具的界面和架构,发现它比我之前想的要扎实得多,核心就一句话:读 Exc…

2026/9/16 12:52:37

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/18 0:01:09

Google Colab 实战:运行模型、数据加载与报错排查

1. 为什么我劝你先搞懂 Colab 的运行模型1.1 Colab 到底是什么,跟本地跑代码差在哪Google Colab 简单说就是一台跑在浏览器里的 Linux 虚拟机,你打开一个 Notebook,背后就连上了一台带 GPU 的远程机器。你在单元格里敲的每一行 Python&#x…

2026/9/18 0:01:09

C语言数据类型与表达式详解

1. C语言数据与数据类型概述在C语言编程中,数据是程序处理的核心对象。理解数据的分类和特性是掌握C语言的基础。C语言中的数据主要分为四大类:常量、变量、表达式和函数。这些数据类型构成了C语言程序的基本元素,每种类型都有其独特的特性和…

2026/9/18 0:01:09

SQL时间字段指定时间段查询:区间语义、索引与时区避坑

上周排查一个线上问题&#xff0c;用户反馈"昨天的订单一条都没查到"&#xff0c;但数据库里明明躺着两千多条。最后定位下来&#xff0c;不是数据丢了&#xff0c;也不是接口挂了&#xff0c;而是那个查询条件把时间段写成了> 2024-05-20 00:00:00 AND < 2024…

2026/9/16 22:55:57

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行&#xff0c;Type-C接口算是典型的“看着简单&#xff0c;做起来全坑”的东西。光引脚就24个&#xff0c;高低速信号、电源、控制线全部塞在一个小小的连接器里&#xff0c;如果PCB布局不做规划&#xff0c;打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/16 22:56:09

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/16 22:56:16

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码