← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
mega_fused_attention.h
Go to the documentation of this file.
1/**
2 * @file mega_fused_attention.h
3 * @brief Mega-Fused Attention Kernel
4 *
5 * Holy grail fusion: RMSNorm → QKV → RoPE → Flash Attention → OutProj + Residual
6 *
7 * All intermediates stay in registers/L1/L2. Single DRAM round-trip.
8 *
9 * Memory Reduction:
10 * Before: ~32KB intermediates per layer (stack/heap)
11 * After: ~8KB total (input + output only)
12 * Reduction: 4-5× per layer, ~100× for full model
13 *
14 * Performance Target:
15 * Move from memory-bound to compute-bound
16 * Expected speedup: 5-10× for attention-heavy workloads
17 */
18
19#ifndef MEGA_FUSED_ATTENTION_H
20#define MEGA_FUSED_ATTENTION_H
21
22#include <stddef.h>
23#include <stdint.h>
24
25#include "ckernel_dtype.h"
26
27/*============================================================================
28 * Configuration
29 *============================================================================*/
30
31/* Tile sizes for streaming through cache hierarchy */
32#ifndef MEGA_FUSE_Q_TILE
33#define MEGA_FUSE_Q_TILE 64
34#endif
35
36#ifndef MEGA_FUSE_KV_TILE
37#define MEGA_FUSE_KV_TILE 64
38#endif
39
40/*============================================================================
41 * Mega-Fused Attention API
42 *============================================================================*/
43
44/**
45 * @brief Mega-fused attention for decode mode (single token)
46 *
47 * This is the "holy grail" - all operations fused, no intermediates to DRAM.
48 *
49 * @param output Output [aligned_embed_dim] (includes residual add)
50 * @param input Input [aligned_embed_dim]
51 * @param residual Residual input [aligned_embed_dim] (or NULL)
52 * @param ln1_gamma RMSNorm gamma [embed_dim]
53 * @param wq Q weights (quantized) [num_heads * aligned_head_dim * aligned_embed_dim]
54 * @param bq Q bias [num_heads * aligned_head_dim] (or NULL)
55 * @param wq_dt Q weight dtype (CK_DT_Q5_0/CK_DT_Q8_0/CK_DT_FP32)
56 * @param wk K weights (quantized) [num_kv_heads * aligned_head_dim * aligned_embed_dim]
57 * @param bk K bias [num_kv_heads * aligned_head_dim] (or NULL)
58 * @param wk_dt K weight dtype (CK_DT_Q5_0/CK_DT_Q8_0/CK_DT_FP32)
59 * @param wv V weights (quantized) [num_kv_heads * aligned_head_dim * aligned_embed_dim]
60 * @param bv V bias [num_kv_heads * aligned_head_dim] (or NULL)
61 * @param wv_dt V weight dtype (CK_DT_Q5_0/CK_DT_Q8_0/CK_DT_FP32)
62 * @param wo Output projection weights (quantized) [aligned_embed_dim * aligned_embed_dim]
63 * @param bo Output bias [aligned_embed_dim] (or NULL)
64 * @param wo_dt Output weight dtype (CK_DT_Q5_0/CK_DT_FP32)
65 * @param kv_cache_k KV cache for K [num_kv_heads * cache_capacity * aligned_head_dim]
66 * @param kv_cache_v KV cache for V [num_kv_heads * cache_capacity * aligned_head_dim]
67 * @param rope_cos RoPE cos [max_seq, head_dim/2]
68 * @param rope_sin RoPE sin [max_seq, head_dim/2]
69 * @param pos Current position in sequence
70 * @param embed_dim Model hidden dimension (unpadded)
71 * @param aligned_embed_dim Aligned hidden dimension
72 * @param num_heads Number of attention heads
73 * @param num_kv_heads Number of KV heads (for GQA)
74 * @param head_dim Head dimension (unpadded)
75 * @param aligned_head_dim Aligned head dimension
76 * @param cache_capacity KV cache capacity (stride in tokens)
77 * @param eps RMSNorm epsilon
78 * @param scratch Scratch buffer from mega_fused_attention_prefill_scratch_size()
79 */
81 float *output,
82 const float *input,
83 const float *residual,
84 const float *ln1_gamma,
85 const float *wq, const float *bq,
86 const float *wk, const float *bk,
87 const float *wv, const float *bv,
88 const float *wo, const float *bo,
89 float *kv_cache_k,
90 float *kv_cache_v,
91 const float *rope_cos,
92 const float *rope_sin,
93 int pos,
94 int embed_dim,
95 int aligned_embed_dim,
96 int num_heads,
97 int num_kv_heads,
98 int head_dim,
99 int aligned_head_dim,
100 int cache_capacity,
101 float eps
102);
103
104/**
105 * Allocation-free decode entry point used by generated runtimes.
106 * q_output_workspace holds 2 * num_heads * aligned_head_dim floats.
107 * kv_workspace holds 2 * num_kv_heads * aligned_head_dim floats.
108 */
110 float *output,
111 const float *input,
112 const float *residual,
113 const float *ln1_gamma,
114 const float *wq, const float *bq,
115 const float *wk, const float *bk,
116 const float *wv, const float *bv,
117 const float *wo, const float *bo,
118 float *kv_cache_k,
119 float *kv_cache_v,
120 const float *rope_cos,
121 const float *rope_sin,
122 int pos,
123 int embed_dim,
124 int aligned_embed_dim,
125 int num_heads,
126 int num_kv_heads,
127 int head_dim,
128 int aligned_head_dim,
129 int cache_capacity,
130 float eps,
131 float *q_output_workspace,
132 size_t q_output_workspace_bytes,
133 float *kv_workspace,
134 size_t kv_workspace_bytes
135);
136
137/**
138 * @brief Mega-fused attention for prefill mode (multiple tokens)
139 *
140 * @param output Output [tokens, aligned_embed_dim] (includes residual add)
141 * @param input Input [tokens, aligned_embed_dim]
142 * @param residual Residual input [tokens, aligned_embed_dim] (or NULL)
143 * @param ln1_gamma RMSNorm gamma [embed_dim]
144 * @param wq Q weights [num_heads * aligned_head_dim * aligned_embed_dim]
145 * @param bq Q bias [num_heads * aligned_head_dim] (or NULL)
146 * @param wk K weights [num_kv_heads * aligned_head_dim * aligned_embed_dim]
147 * @param bk K bias [num_kv_heads * aligned_head_dim] (or NULL)
148 * @param wv V weights [num_kv_heads * aligned_head_dim * aligned_embed_dim]
149 * @param bv V bias [num_kv_heads * aligned_head_dim] (or NULL)
150 * @param wo Output projection weights [num_heads * aligned_embed_dim * aligned_head_dim]
151 * @param bo Output bias [aligned_embed_dim] (or NULL)
152 * @param kv_cache_k KV cache for K [num_kv_heads * cache_capacity * aligned_head_dim]
153 * @param kv_cache_v KV cache for V [num_kv_heads * cache_capacity * aligned_head_dim]
154 * @param rope_cos RoPE cos [max_seq, head_dim/2]
155 * @param rope_sin RoPE sin [max_seq, head_dim/2]
156 * @param start_pos Starting position in KV cache
157 * @param tokens Number of tokens to process
158 * @param cache_capacity KV cache capacity (stride in tokens)
159 * @param embed_dim Model hidden dimension (unpadded)
160 * @param aligned_embed_dim Aligned hidden dimension
161 * @param num_heads Number of attention heads
162 * @param num_kv_heads Number of KV heads
163 * @param head_dim Head dimension (unpadded)
164 * @param aligned_head_dim Aligned head dimension
165 * @param eps RMSNorm epsilon
166 */
168 float *output,
169 const float *input,
170 const float *residual,
171 const float *ln1_gamma,
172 const void *wq, const float *bq, CKDataType wq_dt,
173 const void *wk, const float *bk, CKDataType wk_dt,
174 const void *wv, const float *bv, CKDataType wv_dt,
175 const void *wo, const float *bo, CKDataType wo_dt,
176 float *kv_cache_k,
177 float *kv_cache_v,
178 const float *rope_cos,
179 const float *rope_sin,
180 int start_pos,
181 int tokens,
182 int cache_capacity,
183 int embed_dim,
184 int aligned_embed_dim,
185 int num_heads,
186 int num_kv_heads,
187 int head_dim,
188 int aligned_head_dim,
189 float eps,
190 void *scratch
191);
192
193/**
194 * @brief Mega-fused prefill attention kernel (Q8_0 out-proj)
195 *
196 * Same layout and scratch requirements as mega_fused_attention_prefill.
197 */
199 float *output,
200 const float *input,
201 const float *residual,
202 const float *ln1_gamma,
203 const void *wq, const float *bq, CKDataType wq_dt,
204 const void *wk, const float *bk, CKDataType wk_dt,
205 const void *wv, const float *bv, CKDataType wv_dt,
206 const void *wo, const float *bo, CKDataType wo_dt,
207 float *kv_cache_k,
208 float *kv_cache_v,
209 const float *rope_cos,
210 const float *rope_sin,
211 int start_pos,
212 int tokens,
213 int cache_capacity,
214 int embed_dim,
215 int aligned_embed_dim,
216 int num_heads,
217 int num_kv_heads,
218 int head_dim,
219 int aligned_head_dim,
220 float eps,
221 void *scratch
222);
223
224/** @brief Get scratch buffer size for mega_fused_attention_prefill */
226 int aligned_embed_dim,
227 int num_heads,
228 int aligned_head_dim);
229
230/** @brief Get scratch buffer size for mega_fused_attention_prefill_q8_0 */
232 int aligned_embed_dim,
233 int num_heads,
234 int aligned_head_dim);
235
236/**
237 * @brief Mega-fused post-attention block (out-proj + RMSNorm2 + MLP) for prefill
238 *
239 * Uses head-major attention output and quantized out-proj (Q5_0/Q8_0 weights).
240 */
242 float *output,
243 const float *attn_out,
244 const float *residual,
245 const float *ln2_gamma,
246 const void *wo, const float *bo, CKDataType wo_dt,
247 const void *w1, const float *b1, CKDataType w1_dt,
248 const void *w2, const float *b2, CKDataType w2_dt,
249 int tokens,
250 int embed_dim,
251 int aligned_embed_dim,
252 int num_heads,
253 int aligned_head_dim,
254 int intermediate_dim,
255 int aligned_intermediate_dim,
256 float eps,
257 void *scratch
258);
259
260/** @brief Get scratch buffer size for mega_fused_outproj_mlp_prefill */
262 int aligned_embed_dim,
263 int num_heads,
264 int aligned_head_dim,
265 int aligned_intermediate_dim);
266
267/**
268 * @brief Phase 1: Fused RMSNorm + QKV (intermediates in registers)
269 *
270 * Simpler step: Just fuse RMSNorm with QKV projection.
271 * Q/K/V stay in stack buffers, not DRAM.
272 */
274 float *q_out, // [num_heads * head_dim]
275 float *k_out, // [num_kv_heads * head_dim]
276 float *v_out, // [num_kv_heads * head_dim]
277 const float *input, // [hidden]
278 const float *gamma, // [hidden]
279 const float *W_qkv,
280 const float *b_qkv,
281 int hidden,
282 int num_heads,
283 int num_kv_heads,
284 int head_dim,
285 float eps
286);
287
288/**
289 * @brief Phase 2: Fused RMSNorm + QKV + RoPE
290 *
291 * Q/K stay in output buffers, RoPE applied in-place.
292 */
294 float *q_out,
295 float *k_out,
296 float *v_out,
297 const float *input,
298 const float *gamma,
299 const float *W_qkv,
300 const float *b_qkv,
301 const float *rope_cos,
302 const float *rope_sin,
303 int pos,
304 int hidden,
305 int num_heads,
306 int num_kv_heads,
307 int head_dim,
308 int max_seq,
309 float eps
310);
311
312/**
313 * @brief Get optimal tile sizes for current CPU
314 */
316 int *q_tile, // Output: Q tile size
317 int *kv_tile, // Output: KV tile size
318 int head_dim
319);
320
321/**
322 * @brief Report memory savings from mega-fusion
323 */
325 int hidden,
326 int num_layers,
327 int seq_len
328);
329
330#endif /* MEGA_FUSED_ATTENTION_H */
CKDataType
Supported data types in C-Kernel-Engine.
size_t mega_fused_attention_prefill_q8_0_scratch_size(int tokens, int aligned_embed_dim, int num_heads, int aligned_head_dim)
Get scratch buffer size for mega_fused_attention_prefill_q8_0.
size_t mega_fused_attention_prefill_scratch_size(int tokens, int aligned_embed_dim, int num_heads, int aligned_head_dim)
Get scratch buffer size for mega_fused_attention_prefill.
void mega_fused_attention_prefill(float *output, const float *input, const float *residual, const float *ln1_gamma, const void *wq, const float *bq, CKDataType wq_dt, const void *wk, const float *bk, CKDataType wk_dt, const void *wv, const float *bv, CKDataType wv_dt, const void *wo, const float *bo, CKDataType wo_dt, float *kv_cache_k, float *kv_cache_v, const float *rope_cos, const float *rope_sin, int start_pos, int tokens, int cache_capacity, int embed_dim, int aligned_embed_dim, int num_heads, int num_kv_heads, int head_dim, int aligned_head_dim, float eps, void *scratch)
Mega-fused attention for prefill mode (multiple tokens)
void mega_fuse_report_stats(int hidden, int num_layers, int seq_len)
Report memory savings from mega-fusion.
void mega_fuse_rmsnorm_qkv_rope(float *q_out, float *k_out, float *v_out, const float *input, const float *gamma, const float *W_qkv, const float *b_qkv, const float *rope_cos, const float *rope_sin, int pos, int hidden, int num_heads, int num_kv_heads, int head_dim, int max_seq, float eps)
Phase 2: Fused RMSNorm + QKV + RoPE.
void mega_fuse_get_optimal_tiles(int *q_tile, int *kv_tile, int head_dim)
Get optimal tile sizes for current CPU.
void mega_fused_attention_decode(float *output, const float *input, const float *residual, const float *ln1_gamma, const float *wq, const float *bq, const float *wk, const float *bk, const float *wv, const float *bv, const float *wo, const float *bo, float *kv_cache_k, float *kv_cache_v, const float *rope_cos, const float *rope_sin, int pos, int embed_dim, int aligned_embed_dim, int num_heads, int num_kv_heads, int head_dim, int aligned_head_dim, int cache_capacity, float eps)
Mega-fused attention for decode mode (single token)
void mega_fused_outproj_mlp_prefill(float *output, const float *attn_out, const float *residual, const float *ln2_gamma, const void *wo, const float *bo, CKDataType wo_dt, const void *w1, const float *b1, CKDataType w1_dt, const void *w2, const float *b2, CKDataType w2_dt, int tokens, int embed_dim, int aligned_embed_dim, int num_heads, int aligned_head_dim, int intermediate_dim, int aligned_intermediate_dim, float eps, void *scratch)
Mega-fused post-attention block (out-proj + RMSNorm2 + MLP) for prefill.
void mega_fused_attention_decode_workspace(float *output, const float *input, const float *residual, const float *ln1_gamma, const float *wq, const float *bq, const float *wk, const float *bk, const float *wv, const float *bv, const float *wo, const float *bo, float *kv_cache_k, float *kv_cache_v, const float *rope_cos, const float *rope_sin, int pos, int embed_dim, int aligned_embed_dim, int num_heads, int num_kv_heads, int head_dim, int aligned_head_dim, int cache_capacity, float eps, float *q_output_workspace, size_t q_output_workspace_bytes, float *kv_workspace, size_t kv_workspace_bytes)
Full mega-fused attention for decode.
size_t mega_fused_outproj_mlp_prefill_scratch_size(int tokens, int aligned_embed_dim, int num_heads, int aligned_head_dim, int aligned_intermediate_dim)
Get scratch buffer size for mega_fused_outproj_mlp_prefill.
void mega_fused_attention_prefill_q8_0(float *output, const float *input, const float *residual, const float *ln1_gamma, const void *wq, const float *bq, CKDataType wq_dt, const void *wk, const float *bk, CKDataType wk_dt, const void *wv, const float *bv, CKDataType wv_dt, const void *wo, const float *bo, CKDataType wo_dt, float *kv_cache_k, float *kv_cache_v, const float *rope_cos, const float *rope_sin, int start_pos, int tokens, int cache_capacity, int embed_dim, int aligned_embed_dim, int num_heads, int num_kv_heads, int head_dim, int aligned_head_dim, float eps, void *scratch)
Mega-fused prefill attention kernel (Q8_0 out-proj)
void mega_fuse_rmsnorm_qkv(float *q_out, float *k_out, float *v_out, const float *input, const float *gamma, const float *W_qkv, const float *b_qkv, int hidden, int num_heads, int num_kv_heads, int head_dim, float eps)
Phase 1: Fused RMSNorm + QKV (intermediates in registers)