llama: optimize RWKV7 inference by fusing some graph operators - #25206
llama: optimize RWKV7 inference by fusing some graph operators#25206MollySophia wants to merge 10 commits into
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
Regard PR flags: 1 & 2: This PR makes changes on the existing RWKV7 path, rather than support a new model or feature. The WKV7 op has some semantic changes so that all the supported backends need to be modified at once. |
There was a problem hiding this comment.
Pull request overview
This PR targets RWKV7 inference performance by making RWKV7 decode/time-mix semantics explicit in ggml (new ops + fused kernels/shaders), reducing graph-level operator count and backend launch/dispatch overhead across CUDA, Vulkan, SYCL, Metal, and CPU.
Changes:
- Introduce explicit RWKV ops (
GGML_OP_RWKV_LERP,GGML_OP_RWKV_RK) and route RWKV7 model graph construction through them. - Specialize/fuse RWKV7 hot paths across backends (CUDA kernels, Vulkan shaders/pipelines, SYCL kernels, Metal kernel updates) and adjust RWKV7 WKV7 parameterization (
kk,a) consistently across backends. - Add/extend backend-side graph fusions (e.g., CUDA key-update pattern; Vulkan/CPU add-mul and norm-mul-add fusions) and expand backend op test coverage.
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/test-backend-ops.cpp | Adds backend-op tests for RWKV_LERP and RWKV_RK; updates RWKV_WKV7 test inputs to new signature. |
| src/models/rwkv7-base.cpp | Uses new ggml RWKV ops (lerp/rk) and updates RWKV7 WKV7 call to revised inputs. |
| ggml/src/ggml.c | Adds new ggml ops (RWKV_LERP/RWKV_RK); updates RWKV_WKV7 op signature and metadata strings. |
| ggml/include/ggml.h | Exposes new RWKV APIs and updates RWKV_WKV7 function signature in the public header. |
| ggml/include/ggml-rpc.h | Bumps RPC patch version and updates op-count static_assert to match new ops. |
| ggml/src/ggml-backend-meta.cpp | Marks new RWKV ops as supported for meta backend split-state handling. |
| ggml/src/ggml-cpu/ops.h | Declares CPU implementations for RWKV_LERP/RWKV_RK and new fused CPU paths. |
| ggml/src/ggml-cpu/ops.cpp | Implements CPU RWKV_LERP/RWKV_RK plus fused ADD+MUL and NORM+MUL+ADD compute paths. |
| ggml/src/ggml-cpu/ggml-cpu.c | Wires new RWKV ops into CPU execution and adds CPU-side fusion detection. |
| ggml/src/ggml-cuda/wkv.cu | Updates CUDA RWKV_WKV7 kernel signature and adds a specialized T=1 decode kernel path. |
| ggml/src/ggml-cuda/rwkv.cuh | Declares CUDA fused RWKV helper ops (lerp, rk, and elementwise fusions). |
| ggml/src/ggml-cuda/rwkv.cu | Implements CUDA fused RWKV ops (lerp/rk) and elementwise fusion kernels. |
| ggml/src/ggml-cuda/norm.cuh | Declares fused CUDA norm entry points (norm+mul, norm+mul+add). |
| ggml/src/ggml-cuda/norm.cu | Extends CUDA norm kernel to optionally fuse mul/add, and adds fused wrapper functions. |
| ggml/src/ggml-cuda/ggml-cuda.cu | Dispatches new RWKV ops on CUDA and adds new fusion patterns (incl. RWKV key-update, add-mul, norm fusions). |
| ggml/src/ggml-vulkan/vulkan-shaders/wkv7.comp | Updates Vulkan WKV7 shader to revised (kk, a) math and inline w transform. |
| ggml/src/ggml-vulkan/vulkan-shaders/wkv7_t1.comp | Adds a Vulkan subgroup-based specialized WKV7 T=1 decode shader. |
| ggml/src/ggml-vulkan/vulkan-shaders/rwkv_rk.comp | Adds Vulkan compute shader for fused RWKV_RK. |
| ggml/src/ggml-vulkan/vulkan-shaders/lerp.comp | Adds Vulkan shader for RWKV_LERP. |
| ggml/src/ggml-vulkan/vulkan-shaders/add_mul.comp | Adds Vulkan shader for fused (a+b)*scale pattern. |
| ggml/src/ggml-vulkan/vulkan-shaders/norm_mul_add.comp | Adds Vulkan shader for fused norm*mul+add. |
| ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp | Registers new Vulkan shaders for SPIR-V generation. |
| ggml/src/ggml-vulkan/ggml-vulkan.cpp | Adds Vulkan pipelines/dispatch for new RWKV ops, adds WKV7 T=1 pipeline, and implements new fusion paths. |
| ggml/src/ggml-sycl/wkv.cpp | Updates SYCL WKV7 implementation to revised (kk, a) math and inline w transform. |
| ggml/src/ggml-sycl/rwkv.hpp | Declares SYCL RWKV_LERP and RWKV_RK ops. |
| ggml/src/ggml-sycl/rwkv.cpp | Implements SYCL RWKV_LERP and RWKV_RK kernels. |
| ggml/src/ggml-sycl/backend.hpp | Includes the new SYCL RWKV header into the backend. |
| ggml/src/ggml-sycl/ggml-sycl.cpp | Wires RWKV_LERP and RWKV_RK into SYCL compute and device support checks. |
| ggml/src/ggml-metal/ggml-metal.metal | Updates Metal WKV7 kernel signature and math to match revised (kk, a) formulation and inline w transform. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
I don't think adding new ops for this architecture is worth it IMO. |
I tried to add some fusing rules in the first version, but I didn't find an really elegant way by myself either. Any suggestions on doing fusion instead of adding ops? |
|
I'm trying to figure out a way to add ops without adding a lot of maintenance burden #24646, perhaps wait for some kind of resolution on that. I agree that fusion is not the right way for complicated patterns |
That would be nice! I'll wait for that and avoid these ops. They are indeed not really meaningful enough. |
I suppose this PR will be reworked? |
Yeah thanks. I'll check this soon |
48b26be to
60a04d6
Compare
Assisted-by: Codex
Assisted-by: Codex
Assisted-by: Codex
Assisted-by: Codex
Hi! Sorry for the long delay. I've reworked on this PR and:
The two failed CI tasks seem to be unrelated to this PR (?) |
|
|
||
| if (has_gating) { | ||
| cur = ggml_mul(ctx0, cur, g); | ||
| cur = ggml_mul(ctx0, g, cur); |
There was a problem hiding this comment.
Previously the pattern was ADD -> (logic that computes g) -> MUL
This change should make it to be (logic that computes g) -> ADD -> MUL so that it hits the ADD -> MUL fusion pattern
Summary
This PR optimizes RWKV7 inference on CUDA and Vulkan by reducing kernel-launch and dispatch overhead from small elementwise graph operations, and by specializing the Vulkan RWKV7 single-token WKV path.
The optimizations are implemented as conservative backend graph-pattern fusions. No new ggml operators are introduced, and unsupported shapes or backends continue to execute the original unfused graph.
Changes
Specialize the RWKV7 WKV decode path.
CUDA: optimized WKV7 decode kernel.(Merged in CUDA : add warp-per-row WKV7 kernel for single-token decode #26111)wkv7_t1shader for single-token decode.Fuse RWKV time-mix lerp patterns on CUDA and Vulkan:
SUB -> MUL -> ADDSUB -> REPEAT -> MUL -> ADDcur + (x_prev - cur) * weight.Fuse
ADD -> MULpatterns on CUDA and Vulkan:(x + y) * scale.Fuse affine normalization patterns:
NORM -> MULandNORM -> MUL -> ADD.NORM -> MUL -> ADD.norm(x) * weight + bias.Fuse the RWKV key-adjust pattern on CUDA and Vulkan:
MUL -> MUL -> SUB -> ADDk + (a * (k * k_a) - (k * k_a)).Performance
Hardware:
5d5cb4c3aRWKV7 1.5B
pp512tg128pp512tg128RWKV7 7.2B
pp512tg128tg512pp512tg128tg512Validation
Fusion backend tests:
LERPADD_MULNORM_MUL_ADDKEY_ADJUSTWikiText-2 perplexity is unchanged within noise: