开源llama.cpp Releases·原文 2026年9月20日

llama.cpp b11059让Metal FWHT内核直接读F16输入

llama.cpp发布b11059,Metal后端的FWHT内核把源类型改为模板参数,可直接读取F16,省去转换为F32的拷贝;同时统一supports_op与分发的判断条件,修复不匹配形状导致的崩溃。

llama.cpp发布b11059,主要变更集中在Metal后端的FWHT(Fast Walsh-Hadamard Transform)内核。据提交说明,该内核此前只接受F32输入;这次把源类型改成模板参数,使内核可以直接读取F16源,而不必先准备一份转换后的副本。F32的实例化保持不变。

配套改动包括:pipeline名称现在带上源类型;supports_op在四个内核覆盖的尺寸上接受带Hadamard提示的F16 src1,其余F16 src1路径仍走ggml_metal_supports_mul_mat_op。提交说明称这些即 #27779 提到的测试用例,在M5 Pro上test-backend-ops的MUL_MAT_HADAMARD为 16/16、MUL_MAT为 1265/1265。

该项还修复了一处判断不一致:supports_op仅凭类型、提示和宽度就放行F16 src1,而实际分发还要求src1与dst连续且形状相同。一个通过前者、未通过后者的Hadamard提示MUL_MAT会落到通用路径,那里没有F32 src0配F16 src1的内核,于是因空pipeline中止,报错为kernel not found in any metal library: base = 'kernel_mul_mv_f32_f16_4'。现在ggml_metal_use_fwht持有完整条件,supports_op和分发共用,避免再次分叉。

分支与部署细节

审查还带来一处内核改动:FWHT simdgroup内核中shuffle阶段的三目选择被替换为无分支写法val2 - val + 2*((lane & i) == 0)*val,取值相同但不走select。提交说明称在M5 Pro上以交错的A/B、五轮、首轮丢弃的方式,对block 512、65536 行的Hadamard矩阵乘测量——该配置下内核耗时而非启动占主导——从 1324.6 微秒降至 1285.0 微秒,提升 3.0%,且每一轮都更快。同一提交说明同时指出,在性能套件已有的形状上,该算子运行仅 1.6 至 3.9 微秒,而启动开销下限为 1.6 微秒,因此这一差异在那里不可见。FOR_UNROLL在相同循环上也做了测量,但结果在轮次间变号,所以未被纳入。

  • ggml_metal_use_fwht与ggml_metal_fwht_supported_size从ggml-metal-device.h的static inline移到ggml-metal-common.h声明、ggml-metal-common.cpp实现,跟随ggml_metal_op_mul_mat_use_mm的模式。
  • 命名调整为ggml_metal_op_mul_mat_use_fwht,与 _use_mm成对。
  • 据提交说明,这一移动还修复了macos-latest-arm64构建:ggml-metal-device.h会被tools/tuning经由ggml-metal-tuning.h包含,而该目标没有ggml/src的include路径,原先需要ggml-impl.h获取ggml_get_op_params_i32。
  • 随后一个补丁把ggml_metal_fwht_supported_size改回ggml-metal-common.cpp内的static,并从声明头文件中去掉stdint.h。
  • 又删除了一个m != k的测试用例:Hadamard提示本身承诺src0是Hadamard矩阵,即src0为方阵、dst与src1同形状;该用例不是合法算子,在CPU上把FWHT与一个非方阵src0的真实矩阵乘比较,结果不可能一致。

信息来源

llama.cpp Releases原始来源