llama: optimize RWKV7 inference by fusing some graph operators#25206
llama: optimize RWKV7 inference by fusing some graph operators#25206MollySophia wants to merge 16 commits into
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
Signed-off-by: Molly Sophia <mollysophia379@gmail.com>
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. |
Summary
This PR optimizes RWKV7 inference by reducing graph-level operator overhead
across CUDA and Vulkan, with CPU fallback coverage for the new RWKV-specific
operators.
Although RWKV is architecturally more linear/recurrent than Qwen3.5-style
hybrid models, the current ggml graph for RWKV7 expands into many small
elementwise and reduction operators around WKV. In decode, these small ops
create significant launch/dispatch overhead. This PR makes the main RWKV7 hot
paths explicit ggml ops so backends do not need to rediscover RWKV semantics
through fragile graph-pattern fusion.
Changes
Specialize RWKV7 WKV decode paths.
wkv7_t1decode shader.Add explicit RWKV time-mix lerp op:
RWKV_LERP:cur + (x_prev - cur) * weightFuse CUDA RWKV key-update pattern:
k + (a * ka - ka)Add explicit RWKV7
r_kcorrection op:RWKV_RK:cur + reshape(v * sum_rows((k * r) * r_k))rwkv_rk.compshader.Work around a Vulkan CI correctness failure by disabling the specialized
RWKV7 T=1 subgroup shader on Intel proprietary Windows. This is a separate
commit from the RWKV op changes so it can be reverted independently if the
driver-specific issue is resolved.
Performance
Hardware:
0eca4d490RWKV7 1.5B
GPU model:
rwkv7-g1g-1.5b-20260526-ctx8192-FP16.ggufCPU model:
rwkv7-g1g-1.5b-20260526-ctx8192-q4_0.ggufPrefill
pp512pp512pp512Decode
tg128tg128tg128RWKV7 7.2B
Model:
rwkv7-g1g-7.2b-20260523-ctx8192-F16.ggufPrefill
pp512pp512Decode
tg128tg512tg128tg512Intel Arc Pro B50 / SYCL
Models:
rwkv7-g1g-1.5b-20260526-ctx8192-FP16.ggufrwkv7-g1g-2.9b-20260526-ctx8192-FP16.ggufrwkv7-g1g-7.2b-20260523-ctx8192-F16.ggufPrefill
pp512pp512pp512Decode
tg128tg128tg128Validation
test-backend-ops test -o RWKV_WKV7 -b CUDA0 -j 1test-backend-ops test -o RWKV_WKV7 -b Vulkan0 -j 19.5497 -> 9.55036.4011 -> 6.4013Notes
The largest gains come from reducing small graph operators and backend launches
around RWKV decode. On larger models, decode gains are smaller because mat-vec
work dominates more strongly, but both CUDA and Vulkan still show consistent
positive improvements.
TODO