
ik_llama.cpp 中 DeepSeek 模型wk_b张量按需计算与修复实录从-ctk q8_0 -mla 2崩溃到-rtr运行时重打包【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp本文基于 ik_llama.cpp 仓库中的 issue #271 展开完整梳理了「DeepSeek 系列模型缺少 MLA 所需wk_b/wk_v张量时如何在模型加载阶段按需计算」这一特性的来龙去脉从 PR #259 引入按需计算到 PR #265 意外破坏、GGML_ASSERT(dst-type GGML_TYPE_F32)崩溃复现再到 PR #269/#272 的修复与-rtr运行时重打包、离线重打包两条解决路径。读完本文你将理解wk_b张量的数学来源与量化类型规则掌握-ctk q8_0 -mla 2 -fa -rtr等组合的调试方法并学会用--override-tensor expsCPU、--no-mmap等参数排查混合 CPU/GPU 推理下的类似问题。背景为什么 DeepSeek MLA 需要额外的wk_b张量DeepSeek-V3 / R1 等模型使用 MLAMulti-head Latent Attention架构。与传统 MHA 每层直接保存 K/V 投影不同MLA 在每层只保存一个低秩的wkv_b张量推理时通过矩阵吸收absorption技巧派生出实际参与注意力计算的wk_v与wk_b两个张量wk_v只是wkv_b前一半的视图view不需要额外存储wk_b是wkv_b后一半的转置transposed版本用于把低秩隐变量映射回完整的 head 维度。从源码结构看这一按需派生逻辑集中在 src/llama.cpp 的加载路径中如 src/llama.cpp#L3170 处打印 %s: need to compute %d wk_b/wv_b tensors并在 src/llama-load-tensors.cpp 中为ATTN_K_B等张量建立 3D 的{n_embd_head_qk_nope, kv_lora_rank, n_head}布局参见 src/llama-load-tensors.cpp#L3243-L3254。为什么 mainline GGUF 里没有wk_b早期 llama.cpp 主线的convert_hf_to_gguf.py转换出的 DeepSeek GGUF 文件里只包含wkv_b及部分文件中的wk_v并不包含wk_b。ik_llama.cpp 的 PR #259Prepare wk_b tensors of DeepSeek models on the fly正是为了解决这个问题当模型文件中缺少wk_b时在模型加载阶段现场计算并落盘到对应后端。这也让用户可以直接用 Unsloth 等社区 GGUF原本不带 MLA 张量配合-mla 2 -fa运行 FlashMLA。PR #259 还明确了一条量化规则当wkv_b未被量化时wk_b使用与wkv_b相同的类型fp16或bf16当wkv_b被量化时wk_b一律使用Q8_0。因为对量化张量做转置必须先反量化到fp32为避免低 bpw 量化引入的精度损失直接选用Q8_0。这条规则正是本文后续崩溃分析的关键按需计算wk_b需要把量化张量反量化、转置、再量化底层走的是 ggml 的dup类操作。问题现场PR #265 引入回归llama-server在加载时崩溃issue #271github-data/issues/271由用户ubergarm在 2025-03-19 提交。他正在 Threadripper Pro 24 核 256GB RAM RTX A6000 机器上对比自定义量化与 Unsloth 的UD-Q2_K_XL量化发现在 commit68a5b604PR #264 Make Q8_0 KV cache work with mla2,fa on CUDA上命令运行正常升级到8e549b42PR #265 Allow q8_0 cache on the CPU for FlashMLA-2后同样的命令在模型加载阶段直接崩溃。崩溃复现命令$ CUDA_VISIBLE_DEVICES0, \ ./build/bin/llama-server \ --alias unsloth/DeepSeek-R1-UD_Q2_K_XL \ --model /mnt/raid/models/unsloth/DeepSeek-R1-GGUF/DeepSeek-R1-UD-Q2_K_XL/DeepSeek-R1-UD-Q2_K_XL-00001-of-00005.gguf \ -rtr \ --ctx-size 65536 \ -ctk q8_0 \ -mla 2 -fa \ -amb 512 \ -fmoe \ --n-gpu-layers 63 \ --override-tensor expsCPU \ --parallel 1 \ --threads 24 \ --host 127.0.0.1 \ --port 8080崩溃日志关键片段llm_load_tensors: offloaded 62/62 layers to GPU llm_load_tensors: CPU buffer size 205716.00 MiB llm_load_tensors: CUDA_Host buffer size 497.11 MiB llm_load_tensors: CUDA0 buffer size 9885.95 MiB .................................................................................................... llm_load_tensors: need to compute 61 wk_b tensors /home/w/projects/ik_llama.cpp/ggml/src/ggml.c:10624: GGML_ASSERT(dst-type GGML_TYPE_F32) failed复现要点该模型是5 分片、混合量化361 个 f32 171 个 q2_K 3 个 q3_K 306 个 q4_K 184 个 q6_K 张量61 个重复层全部需要按需计算wk_b同时--override-tensor expsCPU把所有专家张量强制留在 CPU形成CPU 与 GPU 混合推理。用户推断并被作者确认问题出在-ctk q8_0 -mla 2相关代码路径上dup类操作在 CPU 上处理量化张量时触发了断言。根因确认ggml_compute_forward_dup_q被 PR #265 破坏作者 ikawrakow 在 issue 中直接确认PR #265 破坏了按需计算wk_b的路径。而 PR #269Fix ggml_compute_forward_dup_q的说明更加直白I broke it with PR #265. I was testing with a model where the wk_b and wk_v tensors were present, so didnt need to be computed, so didnt notice that the change I made toggml_compute_forward_dup_qbreaks that computation.即作者此前测试的模型自带wk_b/wk_v不需要按需计算因此 PR #265 对ggml_compute_forward_dup_q的改动没有被及时暴露一旦遇到不带 MLA 张量的模型如 Unsloth 量化量化张量的 dup/转置路径就会触发断言。这解释了为什么「同一个模型两个 commit 一个正常一个崩溃」。在 ggml/src/ggml.c 中GGML_ASSERT(dst-type GGML_TYPE_F32)断言出现在多处计算核的出口当前版本中仍能看到这些断言例如 ggml/src/ggml.c#L13084、ggml/src/ggml.c#L13321其语义是某些运算如从量化源做反量化/转置的输出只允许是F32。当 PR #265 改动后量化输入张量在 CPU 上被直接 dup 成非 F32 目标断言随即触发。修复与验证PR #269 修正 dupPR #272 让拷贝/转置支持量化张量修复分两步进行PR #2692025-03-19修复ggml_compute_forward_dup_q恢复量化张量按需计算wk_b的基本能力。作者根据 issue 中断言行号判断用户在无 #269 的版本上复现的崩溃即由此修复覆盖。PR #2722025-03-20作者投入更多精力让 copy/transpose 等操作支持量化张量进一步夯实按需计算路径同时支持了运行时/离线重打包repack特性。用户按作者建议切换到最新主分支127c6ee6build 3597复测虽然断言行号从ggml.c:10624变为ggml.c:10629同一断言、代码移位说明问题仍存在但随后用户使用 PR #272 提供的离线重打包功能重新打包量化模型后问题彻底解决The repacked quant branch and successfully computeswk_btensors with repacked weightsAllows formmap()so things start up much quicker and potential huge pages stuff.离线重打包后的成功运行$ git rev-parse --short HEAD 9fe6fc37 $ numactl -N 0 -m 0 \ ./build/bin/llama-server \ --alias repack/DeepSeek-R1-Q4_K_R4 \ --model /mnt/ai/models/unsloth/repack/DeepSeek-R1-Q4_K_R4.gguf \ --ctx-size 32768 \ -ctk q8_0 \ -mla 2 -fa \ -amb 512 \ -fmoe \ --parallel 1 \ --threads 128 \ --numa numactl \ --host 127.0.0.1 \ --port 8080对应日志llama_model_loader: - type f32: 361 tensors llama_model_loader: - type q4_K: 1 tensors llama_model_loader: - type q4_k_r4: 605 tensors llama_model_loader: - type q6_k_r4: 58 tensors ... llm_load_tensors: need to compute 61 wk_b tensors Computed blk.0.attn_v_b.weight as 128 x 512 x 128 and stored in buffer CPU Computed blk.1.attn_v_b.weight as 128 x 512 x 128 and stored in buffer CPU ... llama_kv_cache_init: CPU KV buffer size 1166.63 MiB llama_new_context_with_model: KV self size 1166.62 MiB, c^KV (q8_0): 1166.62 MiB, kv^T: not used注意日志中的Computed ... as 128 x 512 x 128wk_b的形状为{128, 512, 128}对应 DeepSeek 的n_embd_head_qk_nope 128、kv_lora_rank 512、n_head 128。同时 repack 后模型类型变为q4_k_r4/q6_k_r4等 ik_llama.cpp 特有的 R4 交错格式见 examples/quantize/quantize.cpp 及相关量化工具。-rtr运行时重打包与离线重打包两条路线issue 中反复出现-rtr--run-time-repack参数它的含义在 common/common.cpp 中非常清晰if (arg -rtr || arg --run-time-repack) { params.repack_tensors true; }-rtr会在运行时把张量重打包为 ik_llama.cpp 支持的交错interleavedR4 变体从而获得更快的推理速度而离线重打包则把这一转换提前到模型文件层面带来两个额外收益加载阶段直接得到正确的wk_b按需计算路径对 repack 后的权重同样生效日志显示Computed blk.N.attn_v_b.weight ... stored in buffer CPU由于 repack 后权重布局固定可以正常使用mmap()加载启动更快并为大页huge pages优化留出空间——这正是用户在 issue 中提到的「allows for mmap() so things start up much quicker and potential huge pages stuff」。从 docs/development/on-demand-tensor-reload.md 的说明可以进一步确认-rtr与热插拔hot-swap机制存在一个已知注意事项——恢复restore写回的是普通文件类型无法复现 repack 后的状态无损 repack 在数学上等价但F16 - BF16_R16是有损的因此涉及-rtr的基准测试结果可能不一致。在混合 CPU/GPU 场景排查 NaN 或加载崩溃时这一因素值得留意。延伸问题repack 量化在 perplexity 中的 NaN 排查在 issue 的后续讨论中用户还报告了另一个现象同一份 UnslothQ8_0GGUFmainlinellama.cppb1b132ef跑llama-perplexity-ctk f16 -ctv f16全程干净、Final estimate: PPL 3.3490 /- 0.01849而 ik_llama.cppf2fb15de在相同数据上无论怎么组合-rtr、-mla 1/2、-fa都输出 NaN。作者分析指出日志中Computed ... and stored in buffer CPU信息出现在 perplexity 计算开始之后存在两种可能同步缺失race计算在张量就绪前就开始只要一个 NaN 就会让后续所有批次的结果累积结果全部变成 NaN纯属 I/O 缓冲问题Computed用printf输出、其他日志走LLAMA_LOG_INFO两者缓冲策略不同造成打印顺序错觉。用户给出的验证思路是a) 每次printf后 flushb) 增加isTensorsReady同步标志让 perplexity 计算等待张量就绪。该 issue 最终在 2025-03-24 关闭作者认为按需计算问题已解决剩余的Q8_0NaN 问题被拆分为独立 issue 跟踪可参见 github-data/issues/285。这一案例对实际排障有两点启发排查 NaN 时先区分「计算真的出错」还是「日志交错造成的误判」检查输出通道printfvs 日志系统与同步原语混合 CPU/GPU 推理--override-tensor expsCPU下张量可能落在 CPU buffer 而计算图跨设备执行任何时序问题都可能在 perplexity 这类长任务中放大为全 NaN。可复现实验与调试建议如果你在 ik_llama.cpp 上遇到类似崩溃GGML_ASSERT、ggml_row_size: Assertion ne % ggml_blck_size(type) 0或 NaN可以参考 issue 中的排查步骤确认版本./build/bin/llama-server --version对照 commit。按需计算wk_b的能力自 PR #259 引入dup 修复在 PR #269量化张量拷贝/转置增强在 PR #272——低于对应 commit 的版本遇到 Unsloth 等无 MLA 张量模型时崩溃属预期行为。最小化复现先去掉-rtr与--override-tensor expsCPU用纯 CPU如numactl -N 0 -m 0跑llama-bench或llama-perplexity确认是否与设备混合有关再逐个加回-mla 2 -fa、-ctk q8_0、-fmoe。区分按需计算与重打包路径观察日志中 llm_load_tensors: need to compute 61 wk_b tensors与Computed blk.N... stored in buffer XXX的输出位置与顺序若Computed打印出现在推理开始之后考虑同步问题。优先使用离线 repack相比-rtr运行时重打包离线重打包的权重文件可直接 mmap、启动更快且避免了-rtr在热插拔/恢复场景下的类型还原问题。关键参数速查见 docs/parameters.md 与 common/common.cpp参数含义备注-mla 2 -fa使用 FlashMLA-2 与 Flash Attention-mla 1 -fa仅支持 CPUCUDA 需要-mla 2见 PR #259 讨论-ctk q8_0K cache 类型为 q8_0与 PR #264/#265 引入的量化 KV cache 配合-amb 512/2048attention max batch影响注意力计算分块与 compute buffer 占用-rtr / --run-time-repack运行时把张量重打包为交错 R4 变体定义于 common/common.cpp#L2216-L2217--override-tensor expsCPU强制专家张量放 CPU混合 CPU/GPU 推理wk_b会存到 CPU buffer--no-mmap禁用内存映射加载热插拔工作流要求关闭 mmap见 on-demand-tensor-reload.md结语issue #271 完整记录了一次「新特性引入 → 回归 → 定位 → 修复 → 换路径规避」的典型开源排障闭环PR #259 让 ik_llama.cpp 能对 mainline 转换的 DeepSeek GGUF 按需计算 MLA 所需的wk_b张量PR #265 在改动量纲 dup 实现时误伤该路径导致GGML_ASSERT(dst-type GGML_TYPE_F32)崩溃PR #269/#272 先后修复并在量化张量上补齐了拷贝/转置支持最终用户通过离线 repack 绕开了问题同时保留了mmap()加载与更快的启动速度。对于任何想要在 DeepSeek 系列模型上开启-mla 2 -fa量化 KV cache 的开发者这条「按需计算wk_b repack」的路线与调试经验都是可以直接复用的实战参考。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考