ARTICLE DETAIL

资讯详情

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

ik_llama.cpp Vulkan 后端新增 GGML_OP_FUSED_MUL_UNARY 融合算子:实现原理与性能评估

ik_llama.cpp Vulkan 后端新增 GGML_OP_FUSED_MUL_UNARY 融合算子:实现原理与性能评估 ik_llama.cpp Vulkan 后端新增 GGML_OP_FUSED_MUL_UNARY 融合算子实现原理与性能评估【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp本篇文章以 ik_llama.cpp 仓库 PR #580Vulkan: add GGML_OP_FUSED_MUL_UNARY作者 ikawrakow2025-07-03为骨架深入解析该融合算子在 GGML 计算图中的语义、Vulkan 后端的管道实现与调度路径并完整呈现作者在同一硬件环境下对比 mainline llama.cpp 与 ik_llama.cpp 的 sweep-bench 实测数据。读完本文你将理解mul 一元激活为何值得融合、Vulkan 后端如何为 F32/F16 各挑选专用 shader 管道以及该 PR 对计算图构建去特化的真正价值。PR 背景与动机让 Vulkan 不再被特殊对待在 LLM 的 Transformer 前馈网络中SiLUSwiGLU、GELU等激活函数几乎总是紧跟在一次逐元素乘法之后例如 MoE 的 up/gate 分支、MLP 的 gate 投影。如果计算图把mul与unary拆成两个独立节点后端在执行时就需要两次内存读写而将它们合并为一个GGML_OP_FUSED_MUL_UNARY节点可以在一次 kernel 内核循环里同时完成乘法和激活减少一次中间张量的落盘与回读。作者在 PR 描述中直言该改动带来的性能提升极其微小The tiniest of performance increases, barely measurable但真正的收益在于工程层面——构建计算图时不再需要对 Vulkan 做特殊处理we no longer need to special-case Vulkan when building the graph。也就是说此前图构建阶段需要为 Vulkan 后端单独绕开或改写mul unary模式而有了该算子后CPU、CUDA、Metal、Vulkan 各后端可以共享同一条融合路径图构建逻辑更统一、更干净。算子语义GGML 层的融合定义GGML_OP_FUSED_MUL_UNARY是 GGML 算子枚举的一员定义于 ggml/include/ggml.h紧随GGML_OP_FUSED_RMS_NORM之后属于融合类算子家族其文本名称FUSED_MUL_UNARY记录在 ggml/src/ggml.c 的算子名表中。它的语义实现位于 ggml/src/ggml.c 的ggml_fused_mul_unary_impl核心逻辑如下约束一a必须是连续contiguous张量输出张量result的op被置为GGML_OP_FUSED_MUL_UNARYsrc[0] a、src[1] b一元算子类型通过op_params[0]记录约束二形状相同路径当a与b形状相同时允许的激活算子为GGML_UNARY_OP_GELU、GGML_UNARY_OP_RELU、GGML_UNARY_OP_SILU、GGML_UNARY_OP_SIGMOID约束三形状不同路径当a与b形状不同要求a-ne[0] 1即a为按行广播的权重仅允许GGML_UNARY_OP_SILU或GGML_UNARY_OP_SIGMOID——这正是 MoEup_gate融合fused_up_gate等场景的典型形态a是共享的 gate 权重、b是逐 token 的激活值。在 CPU 端算子分发位于 ggml/src/ggml.c由ggml_compute_forward_fused_mul_unary完成逐元素计算CUDA 与 Metal 后端同样在各自算子列表中处理该 op见 ggml/src/ggml-cuda.cu 与 ggml/src/ggml-metal.m。这说明该算子并非 Vulkan 独有而是 GGML 跨后端的统一融合抽象PR #580 正是把这一能力补齐到了 Vulkan。Vulkan 后端实现管道选择与调度路径Vulkan 后端的实现集中在 ggml/src/ggml-vulkan.cpp可以拆成三个层次1. 专用 shader 管道的注册设备初始化阶段创建了 6 条融合管道每个激活函数各配 F32 与 F16 两个变体ggml/src/ggml-vulkan.cppggml_vk_create_pipeline(device, device-pipeline_fused_mul_silu[0], fused_mul_silu_f32, fused_mul_silu_f32_len, fused_mul_silu_f32_data, ...); ggml_vk_create_pipeline(device, device-pipeline_fused_mul_silu[1], fused_mul_silu_f16, fused_mul_silu_f16_len, fused_mul_silu_f16_data, ...); ggml_vk_create_pipeline(device, device-pipeline_fused_mul_gelu[0], fused_mul_gelu_f32, ...); ggml_vk_create_pipeline(device, device-pipeline_fused_mul_gelu[1], fused_mul_gelu_f16, ...); ggml_vk_create_pipeline(device, device-pipeline_fused_mul_relu[0], fused_mul_relu_f32, ...); ggml_vk_create_pipeline(device, device-pipeline_fused_mul_relu[1], fused_mul_relu_f16, ...);对应管道句柄数组声明于 ggml/src/ggml-vulkan.cpp。2. 算子支持判定与管道匹配在ggml_vk_op_supports_op的 switch 分支ggml/src/ggml-vulkan.cpp中对GGML_OP_FUSED_MUL_UNARY做了严格的类型与激活匹配三个张量src0、src1、dst只接受F32或F16且三者类型必须一致否则返回nullptr表示不支持从dst-op_params[0]读取一元算子类型按SILU、GELU、RELU分别返回对应的fused_mul_*管道并以dst-type GGML_TYPE_F16作为数组下标选择 F16 变体其它一元算子如 SIGMOID 之外的组合直接返回不支持走回退路径。3. 调度与执行执行入口ggml_vk_fused_mul_unaryggml/src/ggml-vulkan.cpp做了三项断言src0 连续、src0 与 src1 同形、src0 与 dst 同形然后调用泛型调度ggml_vk_op_f32vk_op_push_constants以GGML_OP_FUSED_MUL_UNARY为 op、以ggml_nelements(src0)为元素总数下发 GPU 任务。该 op 被列入逐元素计算组的 grid 拆分逻辑ggml/src/ggml-vulkan.cpp与MUL、ADD、UNARY等共享同一套 workgroup 划分策略元素数超过 262144 时按 512×512×Z 三维拆分否则退化为 512×Z 或一维保证大张量下的调度效率。最终在ggml_vk_compute_forward的分发处ggml/src/ggml-vulkan.cpp直接落入ggml_vk_fused_mul_unary。整个链路支持判定 → 管道匹配 → 元素级调度 → 单 kernel 完成 mul激活由此闭合。性能评估同环境下的 sweep-bench 实测作者在 PR 中附带了完整的 sweep-bench 数据。测试环境为RTX-4080 GPU Ryzen-5975WX 主机Nvidia 驱动 575启用 coopmat2 特性模型为 LLaMA-3.1-8B-InstructprefillPP1024、生成TG256N_KV 从 0 递增到 15360。mainline llama.cppbuild 5821PPTGN_KVT_PP sS_PP t/sT_TG sS_TG t/s102425600.2444200.632.74293.37102425610240.2564002.552.73093.78102425620480.2823634.362.82790.57102425630720.2973452.542.89788.36102425640960.3193212.572.95686.62102425651200.3353056.043.04584.08102425661440.3492937.193.12681.90102425671680.3652807.693.18480.40102425681920.3782710.133.28477.97102425692160.3962589.003.36476.101024256102400.4072514.063.45374.131024256112640.4242415.063.51872.771024256122880.4412322.303.62170.701024256133120.4552249.223.70469.121024256143360.4682190.303.78667.621024256153600.4852111.543.85266.45ik_llama.cpp含本 PRPPTGN_KVT_PP sS_PP t/sT_TG sS_TG t/s102425600.2424234.032.67395.77102425610240.2534052.192.64696.74102425620480.2653866.732.71894.20102425630720.2833618.482.77592.25102425640960.2863584.282.83090.45102425651200.2983441.802.90588.13102425661440.3213194.992.98385.81102425671680.3353059.903.03484.37102425681920.3403007.633.08982.87102425692160.3532897.763.12881.831024256102400.3642814.863.19280.211024256112640.3722753.813.24178.991024256122880.3802692.313.29177.781024256133120.3972580.873.37075.971024256143360.4122486.453.44474.331024256153600.4232420.493.49873.19数据解读融合本身收益微小对比两表同配置行prefill 与生成吞吐的差距主要来自 PR 之外的既有差异FUSED_MUL_UNARY带来的直接增益正如作者所说barely measurable——这也是该 PR 定位为工程整洁性改进而非性能突破的原因ik_llama.cpp 在 16k 上下文下整体快 10–15%在 N_KV15360 时mainline 的 prefill 为 2111.54 t/s、生成 66.45 t/s而 ik_llama.cpp 为 2420.49 t/s14.6%与 73.19 t/s10.1%在 N_KV0 时差距约 0.8%生成到 2.6%prefill。需要强调这一对比发生在 ik_llama.cpp尚无显著 Vulkan 专属优化作者原话 there arent any noticeable Vulkan optimizations in ik_llama.cpp yet的前提下且测试环境开启了 coopmat2 特性关于差异来源的推断作者对 mainline 在长上下文下的相对劣势提出一个待验证的猜测——是否 mainline 正在为大统一的 KV cache 重构付出性能代价。这属于作者在 PR 中的个人观察与推测并非定论读者可结合自身硬件与构建版本复测。结语一次为未来铺路的算子补齐PR #580 的价值可以从三个层面理解算子层面Vulkan 后端完整支持GGML_OP_FUSED_MUL_UNARY覆盖 F32/F16 下的 SiLU、GELU、RELU 三种融合激活与 CPU/CUDA/Metal 后端对齐工程层面消除了计算图构建阶段对 Vulkan 的特殊分支处理使各后端共享统一的融合图构建路径降低后续维护与扩展成本数据层面为 ik_llama.cpp 在 Vulkan 路径上的后续专项优化如 KV cache 相关改动、coopmat2 特性的进一步利用提供了基准起点——融合算子已就位后续针对 Vulkan 的深度优化可以在这个统一的图结构上展开而不必再被特判逻辑牵制。对于希望复现的读者可在当前仓库构建 ik_llama.cpp 后使用sweep-bench示例examples/sweep-bench/sweep-bench.cpp与llama-benchexamples/llama-bench/llama-bench.cpp复测同类场景Vulkan 后端相关代码与管道定义均可在 ggml/src/ggml-vulkan.cpp 中查阅。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表