ARTICLE DETAIL

资讯详情

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

ik_llama.cpp Bitnet FFN 融合优化解析:fused mul-silu 为 Metal/CUDA 再提约 1% 推理速度

ik_llama.cpp Bitnet FFN 融合优化解析:fused mul-silu 为 Metal/CUDA 再提约 1% 推理速度 ik_llama.cpp Bitnet FFN 融合优化解析fused mul-silu 为 Metal/CUDA 再提约 1% 推理速度【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp本文聚焦 ik_llama.cppllama.cpp 的一个高性能 fork中针对 Bitnet 1-bit 模型的 FFN前馈网络优化PR #110 将 fused mul-silu融合乘法与 SiLU 激活引入build_bitnet()图构建路径。文章从该 PR 的动机出发结合 build_bitnet.cpp 与 ggml 核心算子实现剖析融合算子的底层原理、调用链与后端支持情况并给出可验证的性能结论边界。读完你将理解为什么融合能省时、Bitnet 为什么绕过了标准 FFN 构建函数以及该优化在 Metal、CUDA 后端上的实际收益。背景Bitnet 支持与 FFN 融合优化的由来ik_llama.cpp 很早就加入了 Bitnet1-bit / 1.58-bit 权重模型的支持并为此设计了专用的量化类型IQ1_BN、IQ2_BN带逐行 scale可同时处理带/不带独立张量 scale 的 Bitnet 模型详见同系列的 PR #106 Bitnet changes。在常规架构上作者 ikawrakow 已将门控投影gate 上投影up 激活的经典 SwiGLU 式 FFN 计算融合为一个算子从而减少中间张量的写出与回读、降低内存带宽压力。这项融合默认通过标准 FFN 构建函数llm_build_ffn()自动生效。然而正如 PR #110 描述中所坦承的I had forgotten thatbuild_bitnet()does not use the standardllm_build_ffnfunction, so the fused mul-silu didnt get used automatically for Bitnet when I added it to llm_build_ffn.即作者在给llm_build_ffn加入 fused mul-silu 时忘了 Bitnet 的图构建函数build_bitnet()并未走这条标准路径导致融合优化对 Bitnet 并未自动生效。PR #110 正是补齐这个遗漏为 Bitnet 的 FFN 显式接入 fused mul-silu。问题根源Bitnet 为何绕开llm_build_ffn在 llama-build-context.cpp 中llm_build_ffn()是绝大多数架构共用的 FFN 构建函数它内部会根据权重类型、是否量化、fused_up_gate开关等条件自动选择最优路径。而 Bitnet 由于权重极度量化1-bit 级别的IQ1_BN/IQ2_BN且需要额外的 scale 缩放处理其旧版图构建函数build_bitnet()在 build_bitnet.cpp 中被独立实现FFN 部分手工展开并未调用llm_build_ffn因此默认享受不到新增的融合优化。这正是 PR #110 要修复的漏网之鱼——优化逻辑加在了公共函数里但 Bitnet 走的是私有路径。fused mul-silu 的底层原理GGML_OP_FUSED_MUL_UNARY先看标准的 SwiGLU 式 FFN 计算gate 路径tmp up_matmul(x) // 上投影 gate gate_matmul(x) // 门控投影 out silu(gate) * tmp // 激活后逐元素相乘未融合时silu(gate)需要先生成一份完整的中间张量再与tmp相乘涉及额外的内存写入与读取。融合后ggml 提供GGML_OP_FUSED_MUL_UNARY算子对两个同形张量先做逐元素乘法、再施加一元激活SiLU、ReLU、GELU 等一步完成silu(gate) * up。其核心实现在 ggml.c 的ggml_fused_mul_unary_impl()GGML_ASSERT(ggml_is_contiguous(a)); // ...形状/算子合法性校验... result-op GGML_OP_FUSED_MUL_UNARY; result-src[0] a; // gate 结果施加 unary result-src[1] b; // up 结果该实现同样支持特例当a-ne[0] 1即 gate 结果为行向量/标量行时可仅对b施加激活并原地融合对应op SILU || SIGMOID分支进一步省去对b的复制。更进一步当 up 与 gate 权重均为量化类型且形状一致时ggml 还提供ggml_fused_up_gate()ggml.c直接把两个矩阵乘up×b、gate×b与激活融合进一个kernelGGML_OP_FUSED_UP_GATE连两个 matmul 结果张量的物化都省掉了。llm_build_ffn()内部正是优先走这条量化融合路径否则回退到ggml_fused_mul_unary()。源码级剖析build_bitnet中的融合调用点从当前仓库源码看build_bitnet.cpp 的 FFN 部分已经完成了 PR #110 所期望的融合改造其关键步骤为struct ggml_tensor *tmp ggml_mul_mat(ctx0, model.layers[il].ffn_up, cur); // ...ffn_up scale 处理... cur ggml_mul_mat(ctx0, model.layers[il].ffn_gate, cur); // ...ffn_gate scale 处理... cur ggml_fused_mul_unary(ctx0, cur, tmp, GGML_UNARY_OP_SILU); cb(cur, ffn_gate_par, il);即ffn_up与ffn_gate两个投影各自完成 matmul 后直接调用ggml_fused_mul_unary(..., GGML_UNARY_OP_SILU)一步完成SiLU 激活 × up 结果的融合计算中间不再物化silu(gate)临时张量。随后依次经过ffn_sub_norm缩放因子1/(ffn_up_scale²)、ffn_down投影再与残差相加。值得说明的架构差异旧版 Bitnetbuild_bitnet()激活函数为 SiLU且 scale 通过权重张量op_params内嵌传递如q_scale、ffn_gate_scale这正是它无法直接复用llm_build_ffn的原因之一1.58-bit 新版build_bitnet_158()build_bitnet.cpp则改用llm_build_ffn(..., LLM_FFN_RELU_SQR, LLM_FFN_PAR, ...)激活为 ReLU 平方scale 使用独立的wo_scale/ffn_down_scale张量——这条路径天然走公共融合逻辑另外受限于 Bitnet 模型 100 维的奇怪 head sizeFlash Attention 无法启用注意力部分使用标准llm_build_kv()见 PR #106这也是 Bitnet 图构建长期保持独立的原因之一。后端支持与性能收益GGML_OP_FUSED_MUL_UNARY已得到主流后端的原生支持可在各自 dispatch 表中查到对应实现Metalggml-metal.m 与 Metal shaderggml-metal.metalCUDAggml-cuda.cu 提供 kernel 实现Vulkanggml-vulkan.cpp 以ggml_vk_op_f32统一入口覆盖该算子。关于收益PR #110 的原话是This gives us another ~1% speedup for TG-128 on Metal and CUDA.即该融合为TG-128单次生成 128 token 的解码吞吐场景在 Metal 与 CUDA 后端带来约 1% 的额外提速。这是作者在 RTX 4080 等环境下实测的增量收益——它建立在 Bitnet 已多轮优化PR #106 中 TG-128 已从约 320 t/s 提升到 368 t/s的基础之上属于锦上添花的带宽优化红利而非量级跃升。需要说明1% 是作者在该 PR 中给出的实验数据具体数值会随模型尺寸、量化类型IQ1_BN/IQ2_BN、后端与硬件环境而浮动。小结PR #110 是一个典型的优化漏网修复案例融合算子的价值在于减少中间张量物化、降低内存带宽压力而 Bitnet 这类独立图构建架构恰恰容易错过公共路径上的通用优化。当前仓库源码已确认build_bitnet()的 FFN 显式调用ggml_fused_mul_unary(ctx0, cur, tmp, GGML_UNARY_OP_SILU)build_bitnet.cpp且该算子在后端层由 Metal、CUDA、Vulkan 共同支持最终为 Metal/CUDA 的 TG-128 场景带来约 1% 的实测提速。对开发者而言这条演进脉络也提供了可迁移的工程经验当你在公共构建函数中引入新的融合优化时务必逐一核对那些绕过公共路径的专属架构如 Bitnet否则优化可能静默失效。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表