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

资讯详情

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

ik_llama.cpp 在 ARM CPU 上输出乱码的排查实录:从 `-DGGML_SVE=ON` 到 `GGML_ARCH_FLAGS` 的 CPU 特性配置指南

ik_llama.cpp 在 ARM CPU 上输出乱码的排查实录:从 `-DGGML_SVE=ON` 到 `GGML_ARCH_FLAGS` 的 CPU 特性配置指南 ik_llama.cpp 在 ARM CPU 上输出乱码的排查实录从-DGGML_SVEON到GGML_ARCH_FLAGS的 CPU 特性配置指南【免费下载链接】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 记录github-data/issues/539 - Bug_ garbage output.md整理而成并结合仓库源码与构建文档进行原理级展开。文章面向在 aarch64/ARM 服务器如 Azure Cobalt、Graviton、Neoverse 系列上部署 ik_llama.cpp 的用户完整复现了模型加载正常但生成输出为乱码这一典型故障的诊断过程、根因分析和最终解决方案读完后你将掌握 ARM 平台下 ik_llama.cpp 的编译特性检测机制、GGML_SVE/GGML_ARCH_FLAGS等构建选项的实际作用以及-rtr运行期重打包在混合负载下的使用边界。问题现象多个模型在 ARM 服务器上生成乱码2025 年 6 月用户jagusztinl在一台 aarch64 Linux 服务器Azure Cobalt ARM CPU64 物理核、512GB 内存上从源码编译了 ik_llama.cppbuild 3751, commit 8b3002bbGCC 14.2.0随后尝试运行多个模型结果无一例外输出无意义内容。最典型的复现命令与输出如下原文照录../ik_llama.cpp/build/bin/llama-cli -m gemma-3-27b-it-Q4_0.gguf --prompt What is the meaning of life?模型加载阶段一切正常llama_model_loader成功解析了 GGUF 元数据gemma3 架构、62 层、262208 词表、上下文 131072llm_load_tensors正常加载了 808 个张量。但生成阶段输出的却是What is the meaning of life?[multimodal][multimodal][multimodal][multimodal][multimodal]换成 Qwen3-32B-Q4_0 后情况类似只是乱码形态不同What is the meaning of life?*:F*GB-4%G0B$4HF;E(H(C6;():%84-HC.$G)$2)536.).C5346D6;C41ADBD6D;-.:G1;;C!7;A!:8DG466)9#:99)3用户补充了关键排查信息CLI 与 server 行为一致带不带-rtr运行时张量重打包都一样换成 gemma IQ4_XS 模型时输出正常但一加上-rtr就又变成乱码且出现典型的重复 token 循环please please please...该机器上所有模型的 prompt processing 阶段看起来都正常问题集中在解码/采样结果上。第一轮排查量化类型、-rtr与编译警告量化类型不是唯一变量用户最初怀疑是 Q4_0 量化本身的问题I tried with IQ4_XS models (gemma) it works perfectly, maybe Q4_0 is bad. 但随后的实验推翻了这一假设——IQ4_XS 在不带-rtr时正常带上-rtr后同样产生乱码与重复循环。这说明问题与具体的量化类型无关而更可能出在运行环境CPU 特性检测或运行时路径上。这里有必要解释-rtr是什么。在 common/common.cpp 中它的定义是-rtr, --run-time-repack repack tensors if interleaved variant is available对应参数默认值为false见 common/common.h。启用后模型加载阶段会把所有支持 row-interleaved_R4/_R8变体的张量在内存中重打包从而在部分 CPU 上获得更好的矩阵乘法性能。需要注意对纯 CPU 推理-rtr通常是安全的因为所有张量留在内存中但如果是 CPU/GPU 混合推理 MoE 模型README.md 明确警告不要使用-rtr重打包后的 k-quantsQ2_K, Q3_K, Q4_K, Q5_K, Q6_K等没有对应的 CUDA row-interleaved 实现会导致这些张量的矩阵乘法永远在 CPU 上执行反而拖慢 prompt processing它与llama-bench的默认行为不同bench 工具默认开启 repackexamples/llama-bench/llama-bench.cpp因此直接对比 bench 数字时要注意该差异。编译期的大量警告用户贴出了完整编译日志其中包含大量来自ggml/src/iqk/目录的警告例如ggml/src/iqk/fa/iqk_fa_templates.h:534:30: warning: dereferencing type-punned pointer will break strict-aliasing rules ggml/src/iqk/iqk_common.h:851:31: warning: always_inline function might not be inlinable unless also declared inline ggml/src/iqk/iqk_gemm_floats.cpp:1039:34: warning: this statement may fall through [-Wimplicit-fallthrough]这些警告主要源于iqkIQK 量化内核库在 ARM NEON 路径下的类型双关type-punning和 inline 提示属于该项目的已知编译噪音与本次乱码问题没有直接因果关系。可以推断它们不会导致生成内容损坏用户也并未把这些警告当作根因。真正值得注意的是ggml/src/iqk/iqk_gemm_1bit.cpp中ggml_vdotq_s32相关的-Waggressive-loop-optimizations警告——它提示编译器在自动向量化时对循环上界的推断可能触发未定义行为这类警告在特定架构/优化等级组合下才可能出现但本案例中最终定位到的问题并不在此。根因定位ARM CPU 特性未正确启用在维护者ikawrakow建议尝试最新构建后用户用 build 3762 (1843ed22) 重新编译验证乱码依旧。随后用户提供了一条决定性的线索——对比两次构建的system_info输出未启用任何 ARM 特定选项编译时system_info: n_threads 64 / 64 | ... | NEON 1 | SVE 0 | ARM_FMA 1 | FP16_VA 0 | ... | MATMUL_INT8 0 | LLAMAFILE 1 |改用-DGGML_SVEON编译后system_info: n_threads 64 / 64 | ... | NEON 1 | SVE 1 | ARM_FMA 1 | FP16_VA 1 | ... | MATMUL_INT8 1 | LLAMAFILE 0 |用户据此判断this is the root cause of the garbage output on this server——默认编译时 ARM 特性宏FP16 向量运算、INT8 矩阵乘等没有被正确启用某些内核走了不匹配的数据路径最终表现为解码结果整体损坏。从源码看 ARM 构建逻辑这个结论可以从 ggml/src/CMakeLists.txt 的 ARM 分支得到印证。在非 MSVC 的 aarch64 分支约 L1080-L1146中构建系统做三件事特性探测用check_cxx_source_compiles探测__ARM_FEATURE_DOTPRODint8 dotprod、__ARM_FEATURE_MATMUL_INT8、__ARM_FEATURE_FP16_VECTOR_ARITHMETIC等只有探测通过才add_compile_definitions对应宏GGML_SVE开关if (GGML_SVE) list(APPEND ARCH_FLAGS -marcharmv8.6-asve)L1136-L1138。注意这不仅仅是启用 SVE而是把整体架构目标抬高到armv8.6-a连带解锁了 armv8.6 基线所具备/编译器允许的 FP16 与 INT8 指令路径GNU 兼容性对 GCC 追加-flax-vector-conversions并说明 else we fail on Gravitons and such否则会在 Graviton 等平台上失败默认GGML_NATIVE只在 GCC 下追加-marchnativeL1139-L1145。因此用户观察到的现象加-DGGML_SVEON后FP16_VA、MATMUL_INT8由 0 变 1本质上是-marcharmv8.6-asve改变了整体架构目标编译器随之启用了更多 ARM 特性代码路径使内核与 CPU 实际能力对齐。需要客观呈现的一点是维护者对这一解法本身表示过疑惑——no usage is made of SVE anywhere in ik_llama.cpp. The only ARM implementation that exists is NEON整个项目没有任何 SVE 用法唯一 ARM 实现是 NEON。结合源码看GGML_SVE的实际作用确实是抬高-march基线而非直接开启 SVE 内核因此它为什么恰好修复乱码在 issue 中没有定论可以推断起作用的更可能是该选项连锁触发的特性宏FP16 向量、INT8 矩阵乘、LLAMAFILE 禁用等让编译产物与 CPU 特性表保持一致。对用户而言更有普适性的做法是下面介绍的GGML_ARCH_FLAGS。最终方案用GGML_ARCH_FLAGS显式指定 CPU 微架构在另一位社区成员saood06的提示下指向GGML_ARCH_FLAGS的用法见 docs/build.md用户最终采用了显式指定微架构的编译方式cmake -B ./build \ -DGGML_LTOON \ -DCMAKE_CXX_FLAGS -flto -Ofast -DINTEGER64 -I${ARMPL_DIR}/include -larmpl_ilp64_mp -lamath -lastring -lm \ -DCMAKE_C_FLAGS -flto -Ofast -DINTEGER64 -I${ARMPL_DIR}/include -larmpl_ilp64_mp -lamath -lastring -lm \ -DGGML_ARCH_FLAGS-mcpuneoverse-n2crcsve2-aessve2-sha3sve2-sm4norngnossbsdotprodi8mmsvenosme其中-DGGML_LTOON启用链接时优化配合-flto -Ofast获得全局优化-DGGML_ARCH_FLAGS会被构建系统原样透传给 C/C 编译命令行源码证据ggml/src/CMakeLists.txt 中的set(ARCH_FLAGS ${GGML_ARCH_FLAGS})-mcpuneoverse-n2...是针对 Azure CobaltArm Neoverse N2 衍生核的微架构目标其中dotprod i8mm显式开启 INT8 点积与矩阵乘指令sve系特性按 CPU 实际能力声明用户同时链接了 ARM Performance Librariesarmpl_ilp64_mp、amath、astring。这也是维护者在 issue 中反复强调的要点Unlike llama.cpp, nothing is automatically set for you on ARM. It is likely you need to set arch options manually.——与 x86 平台相比ARM 平台没有默认的自动架构检测兜底必须手动声明目标微架构。项目在 ARM 上的特性探测逻辑同样印证了这一点MSVC 分支固定用/arch:armv8.2做探测基线ggml/src/CMakeLists.txtGCC/Clang 分支则依赖GGML_NATIVE或显式 flags探测不到就静默降级。修复后的性能验证与负载场景讨论采用上述配置后用户在 64 核 Cobalt VM 上跑出了可用的结果DeepSeek 671B 量化模型CPU 后端KV 使用 q8_0 量化开启 flash attention、MLA、-rtr、fused MoE引擎/配置测试吞吐llama.cppCobalt 优化 ARM 性能库pp51243.27 ± 0.16 t/sllama.cpp同上tg12810.97 ± 0.07 t/sik_llama.cppGGML_ARCH_FLAGS 配置pp51268.19 ± 0.16 t/sik_llama.cpp同上tg12811.54 ± 0.07 t/s需要说明以上数字来自 issue 当事人自报的运行结果属于特定机型、特定量化Q4_0/Q4_K_R4下的个案测量不代表通用性能结论。但 issue 中的讨论对如何正确解读这些数字提出了几点有价值的提醒值得读者参考PP-512 / TG-128 是误导性指标维护者指出真实场景中 KV cache 很少是空的Try running with something more significant in the KV cache (8k-18k tokens)即在 8k~18k token 上下文下再测才贴近实际用sweep-bench测上下文衰减该工具专门用于衡量性能随上下文长度的衰减并自带绘图工具examples/sweep-bench高 ubatch 可提升 PP在内存带宽允许的前提下调大-ubmicro batch能进一步提升 prompt processing 吞吐批量服务用batched-bench如果要让多个用户共享一个实例可用 examples/batched-bench 验证批处理吞吐MLA 版本选择同一次会话中用户曾用 MLA 3-mla 3与 MLA 2-mla 2跑出不同结果切换时要注意模型头文件是否匹配。这些基准工具与-rtr等参数的完整说明可以在 docs/parameters.md 与 examples/llama-bench/llama-bench.cpp 中找到。给 ARM 部署者的实践建议综合本次 issue 的完整过程在 aarch64 服务器上部署 ik_llama.cpp 时建议按以下顺序排查与配置确认 CPU 特性被正确启用启动日志中检查system_info行的NEON、FP16_VA、MATMUL_INT8等标志位若你的 CPU 支持这些特性而日志显示为 0务必手动指定架构优先使用GGML_ARCH_FLAGS显式声明微架构例如-DGGML_ARCH_FLAGS-mcpuneoverse-n2dotprodi8mmsve比依赖GGML_SVE这类间接开关更可控、更可预期遇到乱码先做最小化对比实验固定模型与量化交替开关-rtr、-faflash attention、-ctk/-ctvKV 量化类型逐项缩小变量范围警惕-rtr的适用边界纯 CPU 场景可放心使用混合 CPU/GPU 的 MoE 模型请遵守 README.md 的警告避免启用用llama-bench/sweep-bench替代单一 t/s 数字尤其要覆盖非空 KV cache 的长上下文场景才能得到接近真实负载的结论。回到 issue 本身该问题最终以用户确认-DGGML_SVEON修复、并在GGML_ARCH_FLAGS下获得满意性能而关闭2025-06-26。对于 ARM 平台项目维护者明确表示这是功能可维护但非重点的方向主要开发/测试平台是 AVX2、Zen4 与 Apple SiliconNEON——这提醒 ARM 服务器用户与 x86 相比你需要为编译期架构声明承担更多主动配置的责任而本次 issue 恰恰给出了一个完整可复用的排查范本。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表