phanerozoic commited on
Commit
1e4acca
·
verified ·
1 Parent(s): 1c890a4

Card: standardized form with hero

Browse files
Files changed (2) hide show
  1. CARD.md +91 -115
  2. README.md +91 -115
CARD.md CHANGED
@@ -5,95 +5,27 @@ license: apache-2.0
5
 
6
  # gated-deltanet
7
 
8
- The gated delta rule in recurrent form, loadable through `kernels`. Three of
9
- every four layers in a hybrid-attention model are not attention: they carry a
10
- fixed-size state per head and update it once per token, so memory does not grow
11
- with context. At 48 such layers, 48 heads and a 128 x 128 state the entire
12
- recurrent memory is **144 MB regardless of sequence length**, where attention
13
- over the same context would need gigabytes.
14
-
15
- Reference: transformers' `torch_recurrent_gated_delta_rule`. That layer is
16
- decorated `@use_kernel_forward_from_hub("Qwen3_5GatedDeltaNet")`, so this is
17
- directly substitutable for it.
18
-
19
- ## How it works
20
-
21
- Per token the update is a decay, a read, a rank-one correction and a read:
22
-
23
- ```
24
- S <- S * exp(g) gated decay, one scalar per head
25
- m <- k^T S what the state already predicts for this key
26
- d <- (v - m) * beta the delta, scaled by the write gate
27
- S <- S + k d^T rank-one write
28
- out <- q^T S read with the query
29
- ```
30
-
31
- The delta rule is what separates this from plain linear attention. The state is
32
- corrected by the difference between the value and what the state already holds
33
- for that key, rather than having the value added blindly, so writing the same
34
- key twice does not double its contribution. Two gates control it: `exp(g)`
35
- decides how much of the past survives, `beta` how strongly the correction lands.
36
-
37
- The state is the whole cost, 128 x 128 floats per head, 64 KiB, and a
38
- straightforward implementation reads and writes it several times per token. Here
39
- one block owns one (batch, head) pair and holds the entire state in its threads'
40
- registers for the whole sequence: a thread owns one value column and a slice of
41
- the key rows. The state is read from memory once at the start and written once
42
- at the end, whatever the length, and every intermediate token touches registers
43
- only. Prefill and decode are therefore the same kernel, differing only in how
44
- many tokens the loop runs.
45
-
46
- ## Measured
47
-
48
- RTX 6000 Ada (48 GB), torch 2.10 + CUDA 12.6, 48 heads, 128 x 128 state, against
49
- the eager reference on the same inputs.
50
-
51
- | batch | tokens | eager | this | speedup |
52
- |---|---|---|---|---|
53
- | 1 | 1 | 0.435 ms | 0.028 ms | **15.3x** |
54
- | 1 | 64 | 7.451 ms | 0.347 ms | **21.4x** |
55
- | 1 | 512 | 61.114 ms | 2.787 ms | **21.9x** |
56
- | 4 | 256 | 40.268 ms | 2.468 ms | 16.3x |
57
-
58
- The eager path is a Python loop over timesteps, each step launching several
59
- tensor operations over the full state; this kernel runs the loop on the device
60
- with the state resident in registers.
61
-
62
- State footprint, Bonsai 27B geometry:
63
-
64
- | | |
65
- |---|---|
66
- | per layer, per sequence | 3.0 MB |
67
- | all 48 linear layers | **144 MB, constant in context length** |
68
-
69
- ## Correctness
70
-
71
- Verified on RTX 6000 Ada against transformers 5.13.
72
-
73
- - **Output and final state** agree with the reference to 5.5e-7 relative across
74
- batch 1 to 3, 8 to 256 tokens, 2 to 8 heads, both 64 and 128 dimensions, with
75
- and without the in-kernel L2 normalization of queries and keys.
76
- - **Chunked equals whole.** Running a 96-token sequence in six 16-token calls,
77
- carrying the state, is `torch.equal` to one call. Prefill and decode are the
78
- same operation.
79
- - **Token by token equals whole.** Decoding 48 tokens one at a time is
80
- `torch.equal` to the batched pass, state included.
81
- - **An initial state is respected**, matching the reference given the same
82
- start.
83
- - **Gate semantics.** `beta = 0` leaves the state exactly untouched; a large
84
- negative `g` shrinks it by nine orders of magnitude; `g = 0` with `beta = 0`
85
- is the exact identity.
86
- - **Deterministic.** Repeated runs are bitwise identical.
87
-
88
- ### A stability note, not a kernel limit
89
-
90
- The delta rule is stable only while `beta * |k|^2` stays near or below 2. Raw
91
- N(0,1) keys at dimension 128 give roughly 65, and the recurrence genuinely
92
- diverges: the reference reaches 1.3e26 on such input and this kernel reproduces
93
- that to five significant figures. Real models avoid it by L2 normalizing the
94
- keys, which is what `use_qk_l2norm` does. If you see the state explode, the
95
- input is outside the rule's stable region and both implementations will agree
96
- that it is.
97
 
98
  ## Usage
99
 
@@ -111,8 +43,9 @@ out = gdn.gated_delta_rule(q, k, v, g, beta, state, use_qk_l2norm=True)
111
 
112
  `version` selects the release branch; `trust_remote_code` is required by
113
  `kernels` for publishers without the trusted-publisher mark. `g` is the log
114
- decay: the kernel applies `exp(g)`, matching the reference, so pass the
115
- pre-exponential gate.
 
116
 
117
  ## API
118
 
@@ -122,36 +55,79 @@ pre-exponential gate.
122
  | `new_state(batch, heads, key_dim, value_dim)` | a zeroed `[B, H, Dk, Dv]` fp32 state |
123
  | `GatedDeltaNet(batch, heads, key_dim, value_dim, use_qk_l2norm)` | module holding the state across steps, one per layer |
124
 
125
- `q`, `k` are `[B, T, H, Dk]`; `v` is `[B, T, H, Dv]`; `g`, `beta` are
126
- `[B, T, H]`. Returns `[B, T, H, Dv]`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
  ## Requirements and limits
129
 
130
- - NVIDIA GPU with compute capability 8.0+.
131
- - fp32 arithmetic. The state is a long product chain and low precision would
132
- compound across the sequence; the reference computes in fp32 for the same
133
- reason.
134
- - `Dv` must divide the 256-thread block, `Dk` must be divisible by
135
- `256 / Dv`, and `Dk / (256 / Dv)` must be at most 64. The 128 x 128 geometry
136
- this targets satisfies all three; 64 x 64 also works.
137
- - `Dk` at most 256.
138
- - **Recurrent form only.** Long prefills would run faster in the chunked
139
- formulation, which turns the sequential scan into matrix products at the cost
140
- of a more complex derivation. This kernel keeps the exact recurrence, which is
141
- what makes chunked and token-by-token bitwise identical, and it is already
142
- 20x the eager path.
143
- - Grouped heads are the caller's business: a model with more value heads than
144
- key heads repeats the key and query heads before calling, as the reference
145
- layer does.
146
- - Forward only.
147
 
148
  ## References
149
 
150
- Yang et al., "Gated Delta Networks: Improving Mamba2 with Delta Rule" (2024);
151
- Yang et al., "Parallelizing Linear Transformers with the Delta Rule over
152
- Sequence Length" (2024); Schlag et al., "Linear Transformers Are Secretly Fast
153
- Weight Programmers" (2021); the reference implementation in transformers'
154
- `Qwen3_5GatedDeltaNet`.
155
 
156
  ## License
157
 
 
5
 
6
  # gated-deltanet
7
 
8
+ The gated delta rule in recurrent form, loadable through `kernels`. The
9
+ reference baseline is transformers' `torch_recurrent_gated_delta_rule`, which
10
+ this kernel matches to 5.5e-7 relative and replaces via
11
+ `@use_kernel_forward_from_hub("Qwen3_5GatedDeltaNet")`.
12
+
13
+ Three of every four layers in a hybrid-attention model are not attention:
14
+ they carry a fixed-size state per head and update it once per token, so
15
+ memory does not grow with context. The catch is speed: written in framework
16
+ ops the recurrence is a Python loop that reads and writes the whole state
17
+ several times per token. This kernel holds the entire state in registers for
18
+ the whole sequence, one block per (batch, head) pair, reading it from memory
19
+ once and writing it once whatever the length, which makes prefill and decode
20
+ the same kernel and the eager loop about twenty times slower.
21
+
22
+ ![The 128 by 128 recurrent state blooms, wipes under the retention gate, and re-blooms while the memory line stays flat against attention's climbing KV curve](https://huggingface.co/kernels/phanerozoic/gated-deltanet/resolve/main/media/hero.gif)
23
+
24
+ *One head's 128 x 128 state filmed live across 2,048 tokens of updates,
25
+ including periodic retention-gate wipes (`g` large and negative erases the
26
+ past, then the state re-blooms). At 48 layers the recurrent memory is 144 MB
27
+ at any context; attention's KV cache at the same geometry passes 155 GB by
28
+ 131,072 tokens. Output matches the transformers reference to 1e-6.*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  ## Usage
31
 
 
43
 
44
  `version` selects the release branch; `trust_remote_code` is required by
45
  `kernels` for publishers without the trusted-publisher mark. `g` is the log
46
+ decay: the kernel applies `exp(g)`, matching the reference. `q`, `k` are
47
+ `[B, T, H, Dk]`; `v` is `[B, T, H, Dv]`; `g`, `beta` are `[B, T, H]`;
48
+ returns `[B, T, H, Dv]`.
49
 
50
  ## API
51
 
 
55
  | `new_state(batch, heads, key_dim, value_dim)` | a zeroed `[B, H, Dk, Dv]` fp32 state |
56
  | `GatedDeltaNet(batch, heads, key_dim, value_dim, use_qk_l2norm)` | module holding the state across steps, one per layer |
57
 
58
+ ## Method
59
+
60
+ Per token the update is a decay, a read, a rank-one correction and a read:
61
+
62
+ ```
63
+ S <- S * exp(g) gated decay, one scalar per head
64
+ m <- k^T S what the state already predicts for this key
65
+ d <- (v - m) * beta the delta, scaled by the write gate
66
+ S <- S + k d^T rank-one write
67
+ out <- q^T S read with the query
68
+ ```
69
+
70
+ The delta rule corrects the state by the difference between the value and
71
+ what the state already holds for that key, so writing the same key twice does
72
+ not double its contribution. The state is the whole cost, 64 KiB per head,
73
+ and here one block owns one (batch, head) pair with the state in its threads'
74
+ registers for the whole sequence: a thread owns one value column and a slice
75
+ of the key rows. Every intermediate token touches registers only.
76
+
77
+ ## Measured
78
+
79
+ RTX 6000 Ada, 48 heads, 128 x 128 state, against the eager reference on the
80
+ same inputs:
81
+
82
+ | batch | tokens | eager | this | speedup |
83
+ |---|---|---|---|---|
84
+ | 1 | 1 | 0.435 ms | 0.028 ms | 15.3x |
85
+ | 1 | 64 | 7.451 ms | 0.347 ms | 21.4x |
86
+ | 1 | 512 | 61.114 ms | 2.787 ms | 21.9x |
87
+ | 4 | 256 | 40.268 ms | 2.468 ms | 16.3x |
88
+
89
+ State footprint, Bonsai 27B geometry: 3.0 MB per layer per sequence, 144 MB
90
+ across all 48 linear layers, constant in context length.
91
+
92
+ ## Correctness
93
+
94
+ Verified against transformers 5.13:
95
+
96
+ - Output and final state agree with the reference to 5.5e-7 relative across
97
+ batch 1 to 3, 8 to 256 tokens, 2 to 8 heads, 64 and 128 dimensions, with
98
+ and without the in-kernel L2 normalization.
99
+ - Chunked equals whole: a 96-token sequence in six 16-token calls, carrying
100
+ the state, is `torch.equal` to one call; decoding token by token equals
101
+ the batched pass, state included.
102
+ - Gate semantics: `beta = 0` leaves the state exactly untouched; a large
103
+ negative `g` shrinks it by nine orders of magnitude; `g = 0` with
104
+ `beta = 0` is the exact identity.
105
+ - Deterministic: repeated runs are bitwise identical.
106
+ - The delta rule is stable only while `beta * |k|^2` stays near or below 2;
107
+ real models L2-normalize keys (`use_qk_l2norm`), and on out-of-region
108
+ input this kernel reproduces the reference's divergence to five
109
+ significant figures.
110
 
111
  ## Requirements and limits
112
 
113
+ - NVIDIA GPU with compute capability 8.0+; fp32 arithmetic (the state is a
114
+ long product chain).
115
+ - `Dv` must divide the 256-thread block, `Dk` divisible by `256 / Dv`,
116
+ `Dk / (256 / Dv) <= 64`; `Dk <= 256`. The 128 x 128 and 64 x 64
117
+ geometries satisfy all constraints.
118
+ - Recurrent form only: long prefills would run faster in the chunked
119
+ formulation; this kernel keeps the exact recurrence, which is what makes
120
+ chunked and token-by-token bitwise identical.
121
+ - Grouped heads are the caller's: repeat key and query heads before calling,
122
+ as the reference layer does. Forward only.
 
 
 
 
 
 
 
123
 
124
  ## References
125
 
126
+ Yang et al., "Gated Delta Networks: Improving Mamba2 with Delta Rule"
127
+ (2024); Yang et al., "Parallelizing Linear Transformers with the Delta Rule
128
+ over Sequence Length" (2024); Schlag et al., "Linear Transformers Are
129
+ Secretly Fast Weight Programmers" (2021); the reference implementation in
130
+ transformers' `Qwen3_5GatedDeltaNet`.
131
 
132
  ## License
133
 
README.md CHANGED
@@ -5,95 +5,27 @@ license: apache-2.0
5
 
6
  # gated-deltanet
7
 
8
- The gated delta rule in recurrent form, loadable through `kernels`. Three of
9
- every four layers in a hybrid-attention model are not attention: they carry a
10
- fixed-size state per head and update it once per token, so memory does not grow
11
- with context. At 48 such layers, 48 heads and a 128 x 128 state the entire
12
- recurrent memory is **144 MB regardless of sequence length**, where attention
13
- over the same context would need gigabytes.
14
-
15
- Reference: transformers' `torch_recurrent_gated_delta_rule`. That layer is
16
- decorated `@use_kernel_forward_from_hub("Qwen3_5GatedDeltaNet")`, so this is
17
- directly substitutable for it.
18
-
19
- ## How it works
20
-
21
- Per token the update is a decay, a read, a rank-one correction and a read:
22
-
23
- ```
24
- S <- S * exp(g) gated decay, one scalar per head
25
- m <- k^T S what the state already predicts for this key
26
- d <- (v - m) * beta the delta, scaled by the write gate
27
- S <- S + k d^T rank-one write
28
- out <- q^T S read with the query
29
- ```
30
-
31
- The delta rule is what separates this from plain linear attention. The state is
32
- corrected by the difference between the value and what the state already holds
33
- for that key, rather than having the value added blindly, so writing the same
34
- key twice does not double its contribution. Two gates control it: `exp(g)`
35
- decides how much of the past survives, `beta` how strongly the correction lands.
36
-
37
- The state is the whole cost, 128 x 128 floats per head, 64 KiB, and a
38
- straightforward implementation reads and writes it several times per token. Here
39
- one block owns one (batch, head) pair and holds the entire state in its threads'
40
- registers for the whole sequence: a thread owns one value column and a slice of
41
- the key rows. The state is read from memory once at the start and written once
42
- at the end, whatever the length, and every intermediate token touches registers
43
- only. Prefill and decode are therefore the same kernel, differing only in how
44
- many tokens the loop runs.
45
-
46
- ## Measured
47
-
48
- RTX 6000 Ada (48 GB), torch 2.10 + CUDA 12.6, 48 heads, 128 x 128 state, against
49
- the eager reference on the same inputs.
50
-
51
- | batch | tokens | eager | this | speedup |
52
- |---|---|---|---|---|
53
- | 1 | 1 | 0.435 ms | 0.028 ms | **15.3x** |
54
- | 1 | 64 | 7.451 ms | 0.347 ms | **21.4x** |
55
- | 1 | 512 | 61.114 ms | 2.787 ms | **21.9x** |
56
- | 4 | 256 | 40.268 ms | 2.468 ms | 16.3x |
57
-
58
- The eager path is a Python loop over timesteps, each step launching several
59
- tensor operations over the full state; this kernel runs the loop on the device
60
- with the state resident in registers.
61
-
62
- State footprint, Bonsai 27B geometry:
63
-
64
- | | |
65
- |---|---|
66
- | per layer, per sequence | 3.0 MB |
67
- | all 48 linear layers | **144 MB, constant in context length** |
68
-
69
- ## Correctness
70
-
71
- Verified on RTX 6000 Ada against transformers 5.13.
72
-
73
- - **Output and final state** agree with the reference to 5.5e-7 relative across
74
- batch 1 to 3, 8 to 256 tokens, 2 to 8 heads, both 64 and 128 dimensions, with
75
- and without the in-kernel L2 normalization of queries and keys.
76
- - **Chunked equals whole.** Running a 96-token sequence in six 16-token calls,
77
- carrying the state, is `torch.equal` to one call. Prefill and decode are the
78
- same operation.
79
- - **Token by token equals whole.** Decoding 48 tokens one at a time is
80
- `torch.equal` to the batched pass, state included.
81
- - **An initial state is respected**, matching the reference given the same
82
- start.
83
- - **Gate semantics.** `beta = 0` leaves the state exactly untouched; a large
84
- negative `g` shrinks it by nine orders of magnitude; `g = 0` with `beta = 0`
85
- is the exact identity.
86
- - **Deterministic.** Repeated runs are bitwise identical.
87
-
88
- ### A stability note, not a kernel limit
89
-
90
- The delta rule is stable only while `beta * |k|^2` stays near or below 2. Raw
91
- N(0,1) keys at dimension 128 give roughly 65, and the recurrence genuinely
92
- diverges: the reference reaches 1.3e26 on such input and this kernel reproduces
93
- that to five significant figures. Real models avoid it by L2 normalizing the
94
- keys, which is what `use_qk_l2norm` does. If you see the state explode, the
95
- input is outside the rule's stable region and both implementations will agree
96
- that it is.
97
 
98
  ## Usage
99
 
@@ -111,8 +43,9 @@ out = gdn.gated_delta_rule(q, k, v, g, beta, state, use_qk_l2norm=True)
111
 
112
  `version` selects the release branch; `trust_remote_code` is required by
113
  `kernels` for publishers without the trusted-publisher mark. `g` is the log
114
- decay: the kernel applies `exp(g)`, matching the reference, so pass the
115
- pre-exponential gate.
 
116
 
117
  ## API
118
 
@@ -122,36 +55,79 @@ pre-exponential gate.
122
  | `new_state(batch, heads, key_dim, value_dim)` | a zeroed `[B, H, Dk, Dv]` fp32 state |
123
  | `GatedDeltaNet(batch, heads, key_dim, value_dim, use_qk_l2norm)` | module holding the state across steps, one per layer |
124
 
125
- `q`, `k` are `[B, T, H, Dk]`; `v` is `[B, T, H, Dv]`; `g`, `beta` are
126
- `[B, T, H]`. Returns `[B, T, H, Dv]`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
  ## Requirements and limits
129
 
130
- - NVIDIA GPU with compute capability 8.0+.
131
- - fp32 arithmetic. The state is a long product chain and low precision would
132
- compound across the sequence; the reference computes in fp32 for the same
133
- reason.
134
- - `Dv` must divide the 256-thread block, `Dk` must be divisible by
135
- `256 / Dv`, and `Dk / (256 / Dv)` must be at most 64. The 128 x 128 geometry
136
- this targets satisfies all three; 64 x 64 also works.
137
- - `Dk` at most 256.
138
- - **Recurrent form only.** Long prefills would run faster in the chunked
139
- formulation, which turns the sequential scan into matrix products at the cost
140
- of a more complex derivation. This kernel keeps the exact recurrence, which is
141
- what makes chunked and token-by-token bitwise identical, and it is already
142
- 20x the eager path.
143
- - Grouped heads are the caller's business: a model with more value heads than
144
- key heads repeats the key and query heads before calling, as the reference
145
- layer does.
146
- - Forward only.
147
 
148
  ## References
149
 
150
- Yang et al., "Gated Delta Networks: Improving Mamba2 with Delta Rule" (2024);
151
- Yang et al., "Parallelizing Linear Transformers with the Delta Rule over
152
- Sequence Length" (2024); Schlag et al., "Linear Transformers Are Secretly Fast
153
- Weight Programmers" (2021); the reference implementation in transformers'
154
- `Qwen3_5GatedDeltaNet`.
155
 
156
  ## License
157
 
 
5
 
6
  # gated-deltanet
7
 
8
+ The gated delta rule in recurrent form, loadable through `kernels`. The
9
+ reference baseline is transformers' `torch_recurrent_gated_delta_rule`, which
10
+ this kernel matches to 5.5e-7 relative and replaces via
11
+ `@use_kernel_forward_from_hub("Qwen3_5GatedDeltaNet")`.
12
+
13
+ Three of every four layers in a hybrid-attention model are not attention:
14
+ they carry a fixed-size state per head and update it once per token, so
15
+ memory does not grow with context. The catch is speed: written in framework
16
+ ops the recurrence is a Python loop that reads and writes the whole state
17
+ several times per token. This kernel holds the entire state in registers for
18
+ the whole sequence, one block per (batch, head) pair, reading it from memory
19
+ once and writing it once whatever the length, which makes prefill and decode
20
+ the same kernel and the eager loop about twenty times slower.
21
+
22
+ ![The 128 by 128 recurrent state blooms, wipes under the retention gate, and re-blooms while the memory line stays flat against attention's climbing KV curve](https://huggingface.co/kernels/phanerozoic/gated-deltanet/resolve/main/media/hero.gif)
23
+
24
+ *One head's 128 x 128 state filmed live across 2,048 tokens of updates,
25
+ including periodic retention-gate wipes (`g` large and negative erases the
26
+ past, then the state re-blooms). At 48 layers the recurrent memory is 144 MB
27
+ at any context; attention's KV cache at the same geometry passes 155 GB by
28
+ 131,072 tokens. Output matches the transformers reference to 1e-6.*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  ## Usage
31
 
 
43
 
44
  `version` selects the release branch; `trust_remote_code` is required by
45
  `kernels` for publishers without the trusted-publisher mark. `g` is the log
46
+ decay: the kernel applies `exp(g)`, matching the reference. `q`, `k` are
47
+ `[B, T, H, Dk]`; `v` is `[B, T, H, Dv]`; `g`, `beta` are `[B, T, H]`;
48
+ returns `[B, T, H, Dv]`.
49
 
50
  ## API
51
 
 
55
  | `new_state(batch, heads, key_dim, value_dim)` | a zeroed `[B, H, Dk, Dv]` fp32 state |
56
  | `GatedDeltaNet(batch, heads, key_dim, value_dim, use_qk_l2norm)` | module holding the state across steps, one per layer |
57
 
58
+ ## Method
59
+
60
+ Per token the update is a decay, a read, a rank-one correction and a read:
61
+
62
+ ```
63
+ S <- S * exp(g) gated decay, one scalar per head
64
+ m <- k^T S what the state already predicts for this key
65
+ d <- (v - m) * beta the delta, scaled by the write gate
66
+ S <- S + k d^T rank-one write
67
+ out <- q^T S read with the query
68
+ ```
69
+
70
+ The delta rule corrects the state by the difference between the value and
71
+ what the state already holds for that key, so writing the same key twice does
72
+ not double its contribution. The state is the whole cost, 64 KiB per head,
73
+ and here one block owns one (batch, head) pair with the state in its threads'
74
+ registers for the whole sequence: a thread owns one value column and a slice
75
+ of the key rows. Every intermediate token touches registers only.
76
+
77
+ ## Measured
78
+
79
+ RTX 6000 Ada, 48 heads, 128 x 128 state, against the eager reference on the
80
+ same inputs:
81
+
82
+ | batch | tokens | eager | this | speedup |
83
+ |---|---|---|---|---|
84
+ | 1 | 1 | 0.435 ms | 0.028 ms | 15.3x |
85
+ | 1 | 64 | 7.451 ms | 0.347 ms | 21.4x |
86
+ | 1 | 512 | 61.114 ms | 2.787 ms | 21.9x |
87
+ | 4 | 256 | 40.268 ms | 2.468 ms | 16.3x |
88
+
89
+ State footprint, Bonsai 27B geometry: 3.0 MB per layer per sequence, 144 MB
90
+ across all 48 linear layers, constant in context length.
91
+
92
+ ## Correctness
93
+
94
+ Verified against transformers 5.13:
95
+
96
+ - Output and final state agree with the reference to 5.5e-7 relative across
97
+ batch 1 to 3, 8 to 256 tokens, 2 to 8 heads, 64 and 128 dimensions, with
98
+ and without the in-kernel L2 normalization.
99
+ - Chunked equals whole: a 96-token sequence in six 16-token calls, carrying
100
+ the state, is `torch.equal` to one call; decoding token by token equals
101
+ the batched pass, state included.
102
+ - Gate semantics: `beta = 0` leaves the state exactly untouched; a large
103
+ negative `g` shrinks it by nine orders of magnitude; `g = 0` with
104
+ `beta = 0` is the exact identity.
105
+ - Deterministic: repeated runs are bitwise identical.
106
+ - The delta rule is stable only while `beta * |k|^2` stays near or below 2;
107
+ real models L2-normalize keys (`use_qk_l2norm`), and on out-of-region
108
+ input this kernel reproduces the reference's divergence to five
109
+ significant figures.
110
 
111
  ## Requirements and limits
112
 
113
+ - NVIDIA GPU with compute capability 8.0+; fp32 arithmetic (the state is a
114
+ long product chain).
115
+ - `Dv` must divide the 256-thread block, `Dk` divisible by `256 / Dv`,
116
+ `Dk / (256 / Dv) <= 64`; `Dk <= 256`. The 128 x 128 and 64 x 64
117
+ geometries satisfy all constraints.
118
+ - Recurrent form only: long prefills would run faster in the chunked
119
+ formulation; this kernel keeps the exact recurrence, which is what makes
120
+ chunked and token-by-token bitwise identical.
121
+ - Grouped heads are the caller's: repeat key and query heads before calling,
122
+ as the reference layer does. Forward only.
 
 
 
 
 
 
 
123
 
124
  ## References
125
 
126
+ Yang et al., "Gated Delta Networks: Improving Mamba2 with Delta Rule"
127
+ (2024); Yang et al., "Parallelizing Linear Transformers with the Delta Rule
128
+ over Sequence Length" (2024); Schlag et al., "Linear Transformers Are
129
+ Secretly Fast Weight Programmers" (2021); the reference implementation in
130
+ transformers' `Qwen3_5GatedDeltaNet`.
131
 
132
  ## License
133
 
Free AI Image Generator No sign-up. Instant results. Open Now