ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ik_llama.cpp 编译排错实录:`undefined reference to ‘iqk_mul_mat‘` 的成因、定位与解决

ik_llama.cpp 编译排错实录:`undefined reference to ‘iqk_mul_mat‘` 的成因、定位与解决 ik_llama.cpp 编译排错实录undefined reference to iqk_mul_mat的成因、定位与解决【免费下载链接】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 #59 记录的链接错误展开当用户在特定服务器上执行make llama-server/make llama-bench时链接器报出一连串undefined reference to iqk_mul_mat类错误。文章将完整还原报错现场与排查过程并结合仓库源码ggml/src/iqk/、ggml/src/CMakeLists.txt、ggml/src/ggml.c等剖析 IQK 矩阵乘法内核的编译开关、CPU 指令集依赖与构建系统差异最终给出可落地的排查与规避方案。读完本文你将掌握此类“编译通过、链接失败”类问题在 llama.cpp 系项目中的标准分析路径。一、问题现象一次典型的“链接期”失败2024 年 9 月用户ndavidson19在 ik_llama.cpp 仓库提交了 Issue #592024-09-18 创建2024-09-26 关闭。其核心现象是在Intel Xeon Gold 5117服务器上运行make llama-server或make llama-bench时编译compile阶段一切正常但在链接link阶段ld抛出大量未定义符号错误/usr/bin/ld: ggml/src/ggml.o: in function ggml_compute_forward_flash_attn_ext_f16: ggml.c:(.text0xbdde): undefined reference to iqk_flash_attn_noalibi /usr/bin/ld: ggml/src/ggml.o: in function ggml_compute_forward_mul_mat: ggml.c:(.text0x13aac): undefined reference to iqk_mul_mat /usr/bin/ld: ggml.c:(.text0x14ae6): undefined reference to iqk_mul_mat /usr/bin/ld: ggml.c:(.text0x15109): undefined reference to iqk_mul_mat /usr/bin/ld: ggml/src/ggml.o: in function ggml_compute_forward_mul_mat_id: ggml.c:(.text0x15c49): undefined reference to iqk_mul_mat_moe /usr/bin/ld: ggml/src/ggml-quants.o: in function ggml_vec_dot_q4_0_q8_0: ggml-quants.c:(.text0x24a06): undefined reference to iqk_mul_mat /usr/bin/ld: ggml/src/ggml-quants.o: in function ggml_vec_dot_q4_1_q8_1: ggml-quants.c:(.text0x24b86): undefined reference to iqk_mul_mat /usr/bin/ld: ggml/src/ggml-quants.o: in function ggml_vec_dot_q5_0_q8_0: ggml-quants.c:(.text0x24d16): undefined reference to iqk_mul_mat /usr/bin/ld: ggml/src/ggml-quants.o: in function ggml_vec_dot_q5_1_q8_1: ggml-quants.c:(.text0x24ee6): undefined reference to iqk_mul_mat /usr/bin/ld: ggml/src/ggml-quants.o: in function ggml_vec_dot_q8_0_q8_0: ggml-quants.c:(.text0x250d6): undefined reference to iqk_mul_mat /usr/bin/ld: ggml/src/ggml-quants.o:ggml-quants.c:(.text0x28c26): more undefined references to iqk_mul_mat follow collect2: error: ld returned 1 exit status make: *** [Makefile:1458: llama-server] Error 1值得注意的细节报错集中在ggml 核心对象文件ggml/src/ggml.o、ggml/src/ggml-quants.o中涉及符号横跨矩阵乘法iqk_mul_mat、MoE 门控路由乘法iqk_mul_mat_moe与Flash Attentioniqk_flash_attn_noalibi三类 IQK 内核报错的调用点既出现在ggml_compute_forward_mul_mat普通矩阵乘与ggml_compute_forward_mul_mat_idMoE 专家路由也出现在ggml_vec_dot_q4_0_q8_0等量化向量点积函数中。这些符号全部属于 ik_llama.cpp 的IQKIwan Kawrakow 量化内核体系即该 fork 的核心差异化资产。二、环境对比为什么“这台机器不行、另一台机器行”Issue 中贴出了两台服务器的 CPU 信息这组对比是定位问题的关键线索。故障机Intel Xeon Gold 5117Skylake-SP虚拟化环境24 逻辑 CPUThread(s) per core: 1关键 CPU flags 只到avx、f16c、fma、sse4_2一级没有avx2、bmi1、bmi2flags 中出现hypervisor说明运行在虚拟机中lscpu上报的特性可能被虚拟化软件过滤。正常机Intel Xeon Platinum 8380Ice Lake-SP160 逻辑 CPU双路每路 40 核、双线程具备完整的高级指令集avx2、bmi1、bmi2、avx512f、avx512dq、avx512vl、avx512bw、avx512vbmi、avx512_vnni等用户报告在这台机器上获得了prompt processing 与 token generation 超过 50% 的提升这是 Issue 报告者在其环境中的实测观察非仓库官方基准数据。用户还补充了版本信息故障机上./llama-server --version输出version: 3432 (12bbdb8c)使用 Ubuntu 22.04 的 GCC 11.4.0 构建——也就是说故障机上的二进制本身已经成功构建过而“另一台服务器却构建不出来”。两台机器恰好走向了相反的结果这本身就暗示问题与目标机器的 CPU 特性/编译参数强相关。三、根因剖析从源码看iqk_mul_mat为什么“只声明、未定义”“编译通过、链接失败”通常意味着声明声明头文件被无条件包含了而实现源文件因条件编译被排除。ik_llama.cpp 的 IQK 代码恰好符合这一模式。3.1 IQK 实现受IQK_IMPLEMENT宏门控先看 ggml/src/iqk/iqk_config.h#if defined IQK_IMPLEMENT #undef IQK_IMPLEMENT #endif #if defined __AVX2__ || defined __ARM_FEATURE_DOTPROD #define IQK_IMPLEMENT #endifIQK_IMPLEMENT只在两种情况下被定义x86 平台启用__AVX2__或 ARM 平台启用__ARM_FEATURE_DOTPROD点积指令。换句话说在 x86 上若编译器没有以启用 AVX2 的方式如-mavx2、-marchnative且 CPU 支持 AVX2编译 IQK 源文件IQK_IMPLEMENT就不会生效相关内核实现会被条件编译逻辑整体排除。对照 Issue #59 的两台机器Xeon Gold 5117 的 flags 里根本没有avx2且处于虚拟化环境特性上报受限而 Xeon Platinum 8380 完整支持 AVX-512 家族。可以推断在 5117 上构建时__AVX2__未被定义 →IQK_IMPLEMENT未定义 → ggml/src/iqk/iqk_mul_mat.cpp 等实现文件中的内核函数未产出符号而 ggml/src/ggml.c 与 ggml/src/ggml-quants.c 在GGML_USE_IQK_MULMAT控制下仍会调用这些函数于是链接器报出成片的undefined reference。3.2 调用方ggml 核心无条件引用 IQK 符号从当前仓库源码可以确认这些符号的真实调用点ggml/src/ggml.cggml_compute_forward_mul_mat中#if GGML_USE_IQK_MULMAT分支直接调用iqk_mul_mat_4d(...)尝试走 IQK 路径失败后回退常规路径ggml/src/ggml.cggml_compute_forward_mul_mat_idMoE中调用iqk_mul_mat_moe(...)ggml/src/ggml.cFlash Attention 路径调用iqk_flash_attn_noalibi(...)ggml/src/ggml-quants.c 等L4603、L4900、L5260、L5644、L5655、L12029ggml_vec_dot_q4_0_q8_0、ggml_vec_dot_q4_1_q8_1、ggml_vec_dot_q5_0_q8_0、ggml_vec_dot_q5_1_q8_1、ggml_vec_dot_q6_0_q8_0、ggml_vec_dot_q8_0_q8_0等向量点积函数中均调用iqk_mul_mat(...)。这与 Issue #59 报错栈中的函数名一一对应佐证了“调用方已编译、实现方未编译”的判断。3.3 声明方完整的 C 接口头文件所有被引用的符号都在 ggml/src/iqk/iqk_mul_mat.h 中以extern C声明包括IQK_API bool iqk_mul_mat(long Nx, long Ny, long ne00, int typeA, const void * A, long strideA, int typeB, const void * B, long strideB, float * C, long stride_C, int ith, int nth); IQK_API bool iqk_mul_mat_4d(long Nx, long Ny, long ne00, ...); IQK_API bool iqk_mul_mat_moe(long Nx, long Ny, long ne00, int ne11, ...); IQK_API bool iqk_moe_fused_up_gate(long Nx, long Ny, long ne00, int ne11, int unary_op, ...); IQK_API bool iqk_flash_attn_noalibi(int type_q, int type_mask, float max_bias, ...);头文件被 ggml/src/ggml.c 和 ggml/src/ggml-quants.c 无条件 include。这再次印证声明永远在场实现才是变量。3.4 构建侧Makefile 与 CMake 的差异Issue 中维护者ikawrakow的回复直接点出了第二层问题——顶层 Makefile 是从 llama.cpp 继承来的并未反映真实构建产物依赖。他给出了反例ggml.o的 Makefile 构建规则只声明了两个依赖ggml/src/ggml.o: \ ggml/src/ggml.c \ ggml/include/ggml.h $(CC) $(CFLAGS) -c $ -o $而用gcc -Iggml/include -Iggml/src -MM ggml/src/ggml.c生成的真实依赖却是ggml.o: ggml/src/ggml.c ggml/src/ggml-impl.h ggml/include/ggml.h \ ggml/src/ggml-quants.h ggml/src/ggml-common.h ggml/src/ggml-aarch64.h也就是说Makefile 的依赖图是不完整的。在增量构建、并行构建make -j或跨机器构建时极易出现部分对象文件过期、部分未重编的状态最终把“新旧混杂”的.o交给链接器产生与 Issue #59 完全一致的未定义符号错误。维护者本人也承认“我平时用 CMake所以 Makefile 的健壮性不如预期”。从当前仓库结构看顶层 Makefile 已经不在仓库中仅 examples/batched.swift/Makefile 等零星残留构建已完全由 CMake 驱动这也印证了维护者的路线选择。四、解决方案与排查路径4.1 标准流程先做干净重建无论根因是“依赖图不完整”还是“CPU 特性开关”第一步都应该是彻底清理后重建避免陈旧.o干扰make clean make -j在 Issue #59 中用户反馈这条命令仍复现相同错误随后表示将改用 CMake。这说明单纯的清理在该机器上不足以解决问题——进一步指向了 CPU 指令集门控IQK_IMPLEMENT依赖 AVX2这一深层原因。4.2 首选方案切换到 CMake 构建维护者明确表示自己使用 CMake且当前仓库的推荐构建方式也是 CMake见 README.md 的构建章节cmake -B build -DGGML_NATIVEON cmake --build build --config Release -j$(nproc)CMake 构建的差异在于它通过 ggml/CMakeLists.txt 的option(GGML_IQK_MUL_MAT ggml: use optimized iqk matrix multiplications ON)显式控制 IQK 矩阵乘法并在 ggml/src/CMakeLists.txt 中把实现源文件精确纳入编译单元set (GGML_SOURCES_IQK iqk/iqk_quantize.cpp iqk/iqk_cpu_ops.cpp) if (GGML_IQK_MUL_MAT) message(STATUS Using optimized iqk matrix multiplications) add_compile_definitions(GGML_USE_IQK_MULMAT) set(GGML_SOURCES_IQK_MM iqk/iqk_mul_mat.cpp iqk/iqk_kda.cpp iqk/iqk_flash_attn.cpp iqk/fa/iqk_fa_576_512.cpp iqk/fa/iqk_fa_512_512.cpp ...) endif()一旦GGML_IQK_MUL_MAT打开GGML_USE_IQK_MULMAT编译宏被定义iqk_mul_mat.cpp、iqk_flash_attn.cpp、iqk_gemm_*.cpp等实现全部进入构建链接器便不会再缺符号。CMake 的正确依赖追踪与源码清单管理正是规避“Makefile 依赖图残缺”这类问题的关键。4.3 深层规避CPU 不支持 AVX2 时的选择结合 ggml/src/iqk/iqk_config.h 的IQK_IMPLEMENT门控逻辑可以确认在 x86 平台上AVX2 是 IQK 内核生效的硬前提。对于 Xeon Gold 5117 这类尤其是虚拟化环境中 flags 被过滤的机器合理的选择包括关闭GGML_IQK_MUL_MATcmake -B build -DGGML_IQK_MUL_MATOFF ...退回通用的 ggml 矩阵乘法路径性能会下降但可构建、可运行显式指定兼容指令集如-DCMAKE_C_FLAGS-mavx2之类前提是 CPU 物理上支持 AVX2优先在支持 AVX2 / AVX-512 的机器上构建Issue 中维护者与用户的实测均表明完整指令集如 Ice Lake 的 AVX-512 家族下 IQK 内核带来的性能收益显著。需要说明仓库演进过程中曾有过移除GGML_IQK_MUL_MAT开关的讨论见 PR #457 记录其核心论点是“不使用GGML_IQK_MUL_MAT就没有使用 ik_llama.cpp 的意义”但当前 ggml/CMakeLists.txt 中该选项仍以默认 ON 存在。这从侧面说明IQK 矩阵乘法是 ik_llama.cpp 性能灵魂正常情况下应保持开启只有遇到构建兼容性问题时才考虑关闭。4.4 定位此类问题的通用方法论结合本次 Issue 的完整排查链条可以沉淀出可复用的排错步骤区分编译期/链接期错误全部为undefined reference时先确认声明头文件与实现源文件是否都在编译单元内核对符号归属用nm/objdump -T检查目标文件或库中是否产出该符号如nm ggml/src/iqk/iqk_mul_mat.o | grep iqk_mul_mat检查条件编译开关搜源码中的#if/#ifdef确认宏定义路径本例即GGML_USE_IQK_MULMAT→IQK_IMPLEMENT→__AVX2__核对目标机 CPU 特性lscpu查看 flags警惕虚拟化环境对指令集上报的过滤对比构建系统若 Makefile 与 CMake 行为不一致优先以依赖解析更严格的 CMake 为准并检查 Makefile 依赖图是否完整可用gcc -MM交叉验证完整日志是硬通货维护者在 Issue 中反复索要完整make输出因为只有完整日志才能定位是“哪个 .o 缺符号、哪个源文件没编译”。Issue #59 最终因用户未提供完整日志而关闭这也提示我们提交此类 Issue 时务必附带make全量输出与lscpu信息才能让维护者高效介入。五、结语Issue #59 是理解 ik_llama.cpp 构建体系的一扇窗口它以一次典型的链接期报错串联起了 IQK 内核的指令集门控IQK_IMPLEMENT依赖__AVX2__/__ARM_FEATURE_DOTPROD、CMake 源码清单GGML_IQK_MUL_MAT与GGML_SOURCES_IQK_MM以及Makefile 依赖图缺陷三条线索。对开发者而言遇到同样的undefined reference to iqk_mul_mat时按“干净重建 → 改用 CMake → 核对 CPU 特性/关闭 IQK 选项 → 提供完整日志”的顺序排查即可快速收敛问题而对想深挖 ik_llama.cpp 性能内核的读者ggml/src/iqk/iqk_mul_mat.h、ggml/src/iqk/iqk_config.h 与 ggml/src/iqk/ 目录下的iqk_mul_mat.cpp、iqk_gemm_*.cpp、fa/子目录则是继续研究的上佳起点。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表