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

发布时间:2026/11/5 8:44:36

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/10/24 21:23:09

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

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

2026/10/24 7:40:03

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

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

2026/10/27 8:40:39

无线麦克风与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/11/5 8:43:16

【Java基础知识】方法与注释

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

2026/11/5 8:38:16

学术论文写作工具全解析:从LaTeX到Word公式编辑

1. 论文写作工具全景概览学术写作从来不是单打独斗的过程。记得我博士期间为了赶一篇JCR一区论文,连续72小时对着Word文档调整公式格式的经历,让我深刻意识到专业工具的重要性。如今市面上涌现的论文辅助工具,早已从单纯的文字处理进化到涵盖…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

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

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

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

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

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

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