liangsu9988 commited on
Commit
0175b4d
·
verified ·
1 Parent(s): 3d730ba

Add torch213-cxx11-cu130-aarch64-linux artifact

Browse files
build/torch213-cxx11-cu130-aarch64-linux/__init__.py ADDED
@@ -0,0 +1,874 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FlashRT QKV split, Q/K RMSNorm, and RoPE kernels."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import torch
6
+
7
+ from ._ops import add_op_namespace_prefix, ops
8
+
9
+
10
+ def _check_decode_rope(x: torch.Tensor, weight: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor, out: torch.Tensor, name: str) -> None:
11
+ if x.dim() != 2 or x.shape[1] != 128:
12
+ raise RuntimeError(f"{name} must have shape (heads, 128)")
13
+ if weight.shape != (128,):
14
+ raise RuntimeError("norm weight must have shape (128,)")
15
+ if cos.shape != (64,) or sin.shape != (64,):
16
+ raise RuntimeError("cos and sin must have shape (64,)")
17
+ if out.shape != x.shape:
18
+ raise RuntimeError("out must have the same shape as input")
19
+
20
+
21
+ @torch.library.register_fake(add_op_namespace_prefix("decode_q_norm_rope_stage_bf16"))
22
+ def _decode_q_norm_rope_stage_bf16_fake(
23
+ q_pre: torch.Tensor,
24
+ q_norm_weight: torch.Tensor,
25
+ cos: torch.Tensor,
26
+ sin: torch.Tensor,
27
+ eps: float,
28
+ q_out: torch.Tensor,
29
+ ) -> None:
30
+ _check_decode_rope(q_pre, q_norm_weight, cos, sin, q_out, "q_pre")
31
+ return None
32
+
33
+
34
+ @torch.library.register_fake(add_op_namespace_prefix("decode_k_norm_rope_kvwrite_bf16"))
35
+ def _decode_k_norm_rope_kvwrite_bf16_fake(
36
+ k_pre: torch.Tensor,
37
+ v_pre: torch.Tensor,
38
+ k_norm_weight: torch.Tensor,
39
+ cos: torch.Tensor,
40
+ sin: torch.Tensor,
41
+ eps: float,
42
+ k_cache_dst: torch.Tensor,
43
+ v_cache_dst: torch.Tensor,
44
+ ) -> None:
45
+ _check_decode_rope(k_pre, k_norm_weight, cos, sin, k_cache_dst, "k_pre")
46
+ if v_pre.shape != k_pre.shape or v_cache_dst.shape != k_pre.shape:
47
+ raise RuntimeError("v_pre and v_cache_dst must have shape (n_kv_heads, 128)")
48
+ return None
49
+
50
+
51
+ @torch.library.register_fake(add_op_namespace_prefix("decode_k_norm_rope_kvwrite_devpos_bf16"))
52
+ def _decode_k_norm_rope_kvwrite_devpos_bf16_fake(
53
+ k_pre: torch.Tensor,
54
+ v_pre: torch.Tensor,
55
+ k_norm_weight: torch.Tensor,
56
+ cos: torch.Tensor,
57
+ sin: torch.Tensor,
58
+ cur_pos: torch.Tensor,
59
+ eps: float,
60
+ k_cache: torch.Tensor,
61
+ v_cache: torch.Tensor,
62
+ ) -> None:
63
+ if k_pre.dim() != 2 or k_pre.shape[1] != 128:
64
+ raise RuntimeError("k_pre must have shape (n_kv_heads, 128)")
65
+ n_kv = k_pre.shape[0]
66
+ if v_pre.shape != k_pre.shape:
67
+ raise RuntimeError("v_pre must have shape (n_kv_heads, 128)")
68
+ if k_norm_weight.shape != (128,):
69
+ raise RuntimeError("k_norm_weight must have shape (128,)")
70
+ if cos.shape != (64,) or sin.shape != (64,):
71
+ raise RuntimeError("cos and sin must have shape (64,)")
72
+ if cur_pos.numel() != 1:
73
+ raise RuntimeError("cur_pos must have one int32 element")
74
+ if k_cache.dim() != 3 or k_cache.shape[1:] != (n_kv, 128):
75
+ raise RuntimeError("k_cache must have shape (max_seq_len, n_kv_heads, 128)")
76
+ if v_cache.shape != k_cache.shape:
77
+ raise RuntimeError("v_cache must have the same shape as k_cache")
78
+ return None
79
+
80
+
81
+ @torch.library.register_fake(
82
+ add_op_namespace_prefix("qkv_split_per_head_norm_rope_bf16")
83
+ )
84
+ def _qkv_split_per_head_norm_rope_bf16_fake(
85
+ packed_qkv: torch.Tensor,
86
+ q_norm_weight: torch.Tensor,
87
+ k_norm_weight: torch.Tensor,
88
+ cos: torch.Tensor,
89
+ sin: torch.Tensor,
90
+ q_heads: int,
91
+ kv_heads: int,
92
+ eps: float,
93
+ q_out: torch.Tensor,
94
+ k_out: torch.Tensor,
95
+ v_out: torch.Tensor,
96
+ ) -> None:
97
+ del eps
98
+ batch, seq_len, _ = packed_qkv.shape
99
+ if packed_qkv.shape[2] != (q_heads + 2 * kv_heads) * 128:
100
+ raise RuntimeError("packed_qkv has an invalid GQA width")
101
+ if q_norm_weight.shape != (128,) or k_norm_weight.shape != (128,):
102
+ raise RuntimeError("Q/K norm weights must have shape (128,)")
103
+ if cos.shape != (batch, seq_len, 128) or sin.shape != cos.shape:
104
+ raise RuntimeError("cos and sin must have shape (batch, seq_len, 128)")
105
+ if q_out.shape != (batch, seq_len, q_heads, 128):
106
+ raise RuntimeError(
107
+ "q_out must have shape (batch, seq_len, q_heads, 128)"
108
+ )
109
+ if k_out.shape != (batch, seq_len, kv_heads, 128):
110
+ raise RuntimeError(
111
+ "k_out must have shape (batch, seq_len, kv_heads, 128)"
112
+ )
113
+ if v_out.shape != k_out.shape:
114
+ raise RuntimeError("v_out must have the same shape as k_out")
115
+ return None
116
+
117
+
118
+ @torch.library.register_fake(add_op_namespace_prefix("qkv_split_bias_rope_bf16"))
119
+ def _qkv_split_bias_rope_bf16_fake(
120
+ packed_qkv: torch.Tensor,
121
+ qkv_bias: torch.Tensor,
122
+ cos: torch.Tensor,
123
+ sin: torch.Tensor,
124
+ q_heads: int,
125
+ kv_heads: int,
126
+ head_dim: int,
127
+ q_out: torch.Tensor,
128
+ k_out: torch.Tensor,
129
+ v_out: torch.Tensor,
130
+ ) -> None:
131
+ batch, seq_len, width = packed_qkv.shape
132
+ expected_width = (q_heads + 2 * kv_heads) * head_dim
133
+ if width != expected_width:
134
+ raise RuntimeError("packed_qkv has an invalid QKV width")
135
+ if qkv_bias.shape != (expected_width,):
136
+ raise RuntimeError("qkv_bias has an invalid shape")
137
+ if head_dim < 8 or head_dim > 256 or head_dim % 2:
138
+ raise RuntimeError("head_dim must be even and in [8, 256]")
139
+ if cos.shape not in (
140
+ (batch, seq_len, head_dim // 2),
141
+ (batch, seq_len, head_dim),
142
+ ):
143
+ raise RuntimeError("cos has an invalid shape")
144
+ if sin.shape != cos.shape:
145
+ raise RuntimeError("sin must have the same shape as cos")
146
+ if q_out.shape != (batch, seq_len, q_heads, head_dim):
147
+ raise RuntimeError("q_out has an invalid shape")
148
+ if k_out.shape != (batch, seq_len, kv_heads, head_dim):
149
+ raise RuntimeError("k_out has an invalid shape")
150
+ if v_out.shape != k_out.shape:
151
+ raise RuntimeError("v_out must have the same shape as k_out")
152
+ return None
153
+
154
+
155
+ @torch.library.register_fake(add_op_namespace_prefix("qkv_split_bias_rope_fp16"))
156
+ def _qkv_split_bias_rope_fp16_fake(
157
+ packed_qkv: torch.Tensor,
158
+ qkv_bias: torch.Tensor,
159
+ cos: torch.Tensor,
160
+ sin: torch.Tensor,
161
+ q_heads: int,
162
+ kv_heads: int,
163
+ head_dim: int,
164
+ q_out: torch.Tensor,
165
+ k_out: torch.Tensor,
166
+ v_out: torch.Tensor,
167
+ ) -> None:
168
+ return _qkv_split_bias_rope_bf16_fake(
169
+ packed_qkv,
170
+ qkv_bias,
171
+ cos,
172
+ sin,
173
+ q_heads,
174
+ kv_heads,
175
+ head_dim,
176
+ q_out,
177
+ k_out,
178
+ v_out,
179
+ )
180
+
181
+
182
+ @torch.library.register_fake(add_op_namespace_prefix("qkv_split_rope_kvcache_bf16"))
183
+ def _qkv_split_rope_kvcache_bf16_fake(
184
+ packed_qkv: torch.Tensor,
185
+ rope: torch.Tensor,
186
+ q_heads: int,
187
+ kv_heads: int,
188
+ head_dim: int,
189
+ cache_offset: int,
190
+ q_out: torch.Tensor,
191
+ k_cache: torch.Tensor,
192
+ v_cache: torch.Tensor,
193
+ ) -> None:
194
+ _check_packed_gqa_qkv(packed_qkv, q_heads, kv_heads, head_dim)
195
+ batch, seq_len, _ = packed_qkv.shape
196
+ if rope.dim() != 2 or rope.shape[0] < seq_len or rope.shape[1] != head_dim:
197
+ raise RuntimeError("rope must have shape (>= seq_len, head_dim)")
198
+ if q_out.shape != (batch, seq_len, q_heads, head_dim):
199
+ raise RuntimeError("q_out must have shape (batch, seq_len, q_heads, head_dim)")
200
+ if k_cache.dim() != 4 or k_cache.shape[0] != batch or k_cache.shape[2:] != (kv_heads, head_dim):
201
+ raise RuntimeError("k_cache must have shape (batch, max_seq_len, kv_heads, head_dim)")
202
+ if v_cache.shape != k_cache.shape:
203
+ raise RuntimeError("v_cache must have the same shape as k_cache")
204
+ if cache_offset < 0 or cache_offset + seq_len > k_cache.shape[1]:
205
+ raise RuntimeError("cache_offset + seq_len must be within k_cache.shape[1]")
206
+ return None
207
+
208
+
209
+ @torch.library.register_fake(add_op_namespace_prefix("qkv_split_bf16"))
210
+ def _qkv_split_bf16_fake(
211
+ packed_qkv: torch.Tensor,
212
+ heads: int,
213
+ head_dim: int,
214
+ q_out: torch.Tensor,
215
+ k_out: torch.Tensor,
216
+ v_out: torch.Tensor,
217
+ ) -> None:
218
+ if packed_qkv.dim() != 3:
219
+ raise RuntimeError("packed_qkv must have shape (batch, seq_len, 3 * heads * head_dim)")
220
+ batch, seq_len, cols = packed_qkv.shape
221
+ if cols != 3 * heads * head_dim:
222
+ raise RuntimeError("packed_qkv.shape[2] must be 3 * heads * head_dim")
223
+ out_shape = (batch, seq_len, heads, head_dim)
224
+ if q_out.shape != out_shape or k_out.shape != out_shape or v_out.shape != out_shape:
225
+ raise RuntimeError("q_out, k_out, and v_out must have shape (batch, seq_len, heads, head_dim)")
226
+ return None
227
+
228
+
229
+ @torch.library.register_fake(add_op_namespace_prefix("qkv_split_norm_rope_bf16"))
230
+ def _qkv_split_norm_rope_bf16_fake(
231
+ packed_qkv: torch.Tensor,
232
+ norm_q_weight: torch.Tensor,
233
+ norm_k_weight: torch.Tensor,
234
+ freqs_re: torch.Tensor,
235
+ freqs_im: torch.Tensor,
236
+ heads: int,
237
+ head_dim: int,
238
+ rope_seq_len: int,
239
+ eps: float,
240
+ q_out: torch.Tensor,
241
+ k_out: torch.Tensor,
242
+ ) -> None:
243
+ if packed_qkv.dim() != 3:
244
+ raise RuntimeError("packed_qkv must have shape (batch, seq_len, 3 * heads * head_dim)")
245
+ batch, seq_len, cols = packed_qkv.shape
246
+ dim = heads * head_dim
247
+ if cols != 3 * dim:
248
+ raise RuntimeError("packed_qkv.shape[2] must be 3 * heads * head_dim")
249
+ if norm_q_weight.shape != (dim,) or norm_k_weight.shape != (dim,):
250
+ raise RuntimeError("norm weights must have shape (heads * head_dim,)")
251
+ if freqs_re.dim() != 2 or freqs_re.shape[1] != head_dim // 2:
252
+ raise RuntimeError("freqs_re must have shape (rope_seq_len, head_dim / 2)")
253
+ if freqs_im.shape != freqs_re.shape:
254
+ raise RuntimeError("freqs_im must have the same shape as freqs_re")
255
+ if q_out.shape != (batch, seq_len, heads, head_dim):
256
+ raise RuntimeError("q_out must have shape (batch, seq_len, heads, head_dim)")
257
+ if k_out.shape != q_out.shape:
258
+ raise RuntimeError("k_out must have the same shape as q_out")
259
+ return None
260
+
261
+
262
+ @torch.library.register_fake(add_op_namespace_prefix("qkv_split_bias_norm_rope_v_bf16"))
263
+ def _qkv_split_bias_norm_rope_v_bf16_fake(
264
+ packed_qkv: torch.Tensor,
265
+ qkv_bias: torch.Tensor,
266
+ norm_q_weight: torch.Tensor,
267
+ norm_k_weight: torch.Tensor,
268
+ freqs_re: torch.Tensor,
269
+ freqs_im: torch.Tensor,
270
+ heads: int,
271
+ head_dim: int,
272
+ rope_seq_len: int,
273
+ eps: float,
274
+ q_out: torch.Tensor,
275
+ k_out: torch.Tensor,
276
+ v_out: torch.Tensor,
277
+ ) -> None:
278
+ _check_packed_qkv(packed_qkv, norm_q_weight, norm_k_weight, heads, head_dim)
279
+ batch, seq_len, _ = packed_qkv.shape
280
+ dim = heads * head_dim
281
+ if qkv_bias.shape != (3 * dim,):
282
+ raise RuntimeError("qkv_bias must have shape (3 * heads * head_dim,)")
283
+ _check_freqs(freqs_re, freqs_im, head_dim, rope_seq_len)
284
+ out_shape = (batch, seq_len, heads, head_dim)
285
+ if q_out.shape != out_shape or k_out.shape != out_shape or v_out.shape != out_shape:
286
+ raise RuntimeError("q_out, k_out, and v_out must have shape (batch, seq_len, heads, head_dim)")
287
+ return None
288
+
289
+
290
+ @torch.library.register_fake(add_op_namespace_prefix("qkv_split_bias_norm_rope_v_cat_bf16"))
291
+ def _qkv_split_bias_norm_rope_v_cat_bf16_fake(
292
+ packed_qkv: torch.Tensor,
293
+ qkv_bias: torch.Tensor,
294
+ norm_q_weight: torch.Tensor,
295
+ norm_k_weight: torch.Tensor,
296
+ freqs_re: torch.Tensor,
297
+ freqs_im: torch.Tensor,
298
+ heads: int,
299
+ head_dim: int,
300
+ video_offset: int,
301
+ rope_seq_len: int,
302
+ eps: float,
303
+ q_cat_out: torch.Tensor,
304
+ k_cat_out: torch.Tensor,
305
+ v_cat_out: torch.Tensor,
306
+ ) -> None:
307
+ _check_packed_qkv(packed_qkv, norm_q_weight, norm_k_weight, heads, head_dim)
308
+ batch, seq_len, _ = packed_qkv.shape
309
+ dim = heads * head_dim
310
+ if qkv_bias.shape != (3 * dim,):
311
+ raise RuntimeError("qkv_bias must have shape (3 * heads * head_dim,)")
312
+ if q_cat_out.dim() != 4:
313
+ raise RuntimeError("q_cat_out must have shape (batch, total_seq_len, heads, head_dim)")
314
+ total_seq_len = q_cat_out.shape[1]
315
+ if video_offset < 0 or video_offset + seq_len > total_seq_len:
316
+ raise RuntimeError("video_offset + packed_qkv.shape[1] must be within q_cat_out.shape[1]")
317
+ _check_freqs(freqs_re, freqs_im, head_dim, rope_seq_len)
318
+ out_shape = (batch, total_seq_len, heads, head_dim)
319
+ if q_cat_out.shape != out_shape or k_cat_out.shape != out_shape or v_cat_out.shape != out_shape:
320
+ raise RuntimeError("cat outputs must have shape (batch, total_seq_len, heads, head_dim)")
321
+ return None
322
+
323
+
324
+ @torch.library.register_fake(add_op_namespace_prefix("qkv_split_joint3_cat_bf16"))
325
+ def _qkv_split_joint3_cat_bf16_fake(
326
+ packed_v: torch.Tensor,
327
+ qkv_v_bias: torch.Tensor,
328
+ norm_v_q_weight: torch.Tensor,
329
+ norm_v_k_weight: torch.Tensor,
330
+ freqs_re: torch.Tensor,
331
+ freqs_im: torch.Tensor,
332
+ packed_a: torch.Tensor,
333
+ norm_a_q_weight: torch.Tensor,
334
+ norm_a_k_weight: torch.Tensor,
335
+ packed_u: torch.Tensor,
336
+ norm_u_q_weight: torch.Tensor,
337
+ norm_u_k_weight: torch.Tensor,
338
+ heads: int,
339
+ head_dim: int,
340
+ rope_seq_len: int,
341
+ eps_v: float,
342
+ eps_a: float,
343
+ eps_u: float,
344
+ q_cat_out: torch.Tensor,
345
+ k_cat_out: torch.Tensor,
346
+ v_cat_out: torch.Tensor,
347
+ ) -> None:
348
+ _check_packed_qkv(packed_v, norm_v_q_weight, norm_v_k_weight, heads, head_dim)
349
+ _check_packed_qkv(packed_a, norm_a_q_weight, norm_a_k_weight, heads, head_dim)
350
+ _check_packed_qkv(packed_u, norm_u_q_weight, norm_u_k_weight, heads, head_dim)
351
+ batch = packed_v.shape[0]
352
+ if batch != 1 or packed_a.shape[0] != batch or packed_u.shape[0] != batch:
353
+ raise RuntimeError("qkv_split_joint3_cat_bf16 currently supports batch == 1")
354
+ total_seq_len = packed_v.shape[1] + packed_a.shape[1] + packed_u.shape[1]
355
+ dim = heads * head_dim
356
+ if qkv_v_bias.shape != (3 * dim,):
357
+ raise RuntimeError("qkv_v_bias must have shape (3 * heads * head_dim,)")
358
+ _check_freqs(freqs_re, freqs_im, head_dim, rope_seq_len)
359
+ out_shape = (batch, total_seq_len, heads, head_dim)
360
+ if q_cat_out.shape != out_shape or k_cat_out.shape != out_shape or v_cat_out.shape != out_shape:
361
+ raise RuntimeError("cat outputs must have shape (1, L_v + L_a + L_u, heads, head_dim)")
362
+ return None
363
+
364
+
365
+ def _check_packed_qkv(
366
+ packed_qkv: torch.Tensor,
367
+ norm_q_weight: torch.Tensor,
368
+ norm_k_weight: torch.Tensor,
369
+ heads: int,
370
+ head_dim: int,
371
+ ) -> None:
372
+ if packed_qkv.dim() != 3:
373
+ raise RuntimeError("packed_qkv must have shape (batch, seq_len, 3 * heads * head_dim)")
374
+ dim = heads * head_dim
375
+ if head_dim % 2 != 0 or packed_qkv.shape[2] != 3 * dim:
376
+ raise RuntimeError("packed_qkv.shape[2] must be 3 * heads * head_dim and head_dim must be even")
377
+ if norm_q_weight.shape != (dim,) or norm_k_weight.shape != (dim,):
378
+ raise RuntimeError("norm weights must have shape (heads * head_dim,)")
379
+
380
+
381
+ def _check_packed_gqa_qkv(
382
+ packed_qkv: torch.Tensor,
383
+ q_heads: int,
384
+ kv_heads: int,
385
+ head_dim: int,
386
+ ) -> None:
387
+ if packed_qkv.dim() != 3:
388
+ raise RuntimeError("packed_qkv must have shape (batch, seq_len, (q_heads + 2 * kv_heads) * head_dim)")
389
+ if q_heads <= 0 or kv_heads <= 0 or head_dim <= 0 or head_dim % 2 != 0:
390
+ raise RuntimeError("q_heads, kv_heads, and even head_dim must be positive")
391
+ expected = (q_heads + 2 * kv_heads) * head_dim
392
+ if packed_qkv.shape[2] != expected:
393
+ raise RuntimeError("packed_qkv.shape[2] must be (q_heads + 2 * kv_heads) * head_dim")
394
+
395
+
396
+ def _check_freqs(
397
+ freqs_re: torch.Tensor,
398
+ freqs_im: torch.Tensor,
399
+ head_dim: int,
400
+ rope_seq_len: int,
401
+ ) -> None:
402
+ if freqs_re.dim() != 2 or freqs_re.shape[1] != head_dim // 2:
403
+ raise RuntimeError("freqs_re must have shape (rope_seq_len, head_dim / 2)")
404
+ if freqs_im.shape != freqs_re.shape:
405
+ raise RuntimeError("freqs_im must have the same shape as freqs_re")
406
+ if rope_seq_len < 0 or freqs_re.shape[0] < rope_seq_len:
407
+ raise RuntimeError("freqs_re must have at least rope_seq_len rows")
408
+
409
+
410
+ def qkv_split_norm_rope_bf16(
411
+ packed_qkv: torch.Tensor,
412
+ norm_q_weight: torch.Tensor,
413
+ norm_k_weight: torch.Tensor,
414
+ freqs_re: torch.Tensor,
415
+ freqs_im: torch.Tensor,
416
+ heads: int,
417
+ head_dim: int,
418
+ rope_seq_len: int | None = None,
419
+ eps: float = 1e-6,
420
+ q_out: torch.Tensor | None = None,
421
+ k_out: torch.Tensor | None = None,
422
+ ) -> tuple[torch.Tensor, torch.Tensor]:
423
+ """Split packed QKV, RMSNorm Q/K, apply RoPE, and return Q/K tensors.
424
+
425
+ ``packed_qkv`` has shape ``(batch, seq_len, 3 * heads * head_dim)``.
426
+ Outputs have shape ``(batch, seq_len, heads, head_dim)``.
427
+ """
428
+
429
+ if rope_seq_len is None:
430
+ rope_seq_len = packed_qkv.shape[1]
431
+ out_shape = (packed_qkv.shape[0], packed_qkv.shape[1], heads, head_dim)
432
+ if q_out is None:
433
+ q_out = torch.empty(out_shape, device=packed_qkv.device, dtype=torch.bfloat16)
434
+ if k_out is None:
435
+ k_out = torch.empty(out_shape, device=packed_qkv.device, dtype=torch.bfloat16)
436
+ ops.qkv_split_norm_rope_bf16(
437
+ packed_qkv,
438
+ norm_q_weight,
439
+ norm_k_weight,
440
+ freqs_re,
441
+ freqs_im,
442
+ int(heads),
443
+ int(head_dim),
444
+ int(rope_seq_len),
445
+ float(eps),
446
+ q_out,
447
+ k_out,
448
+ )
449
+ return q_out, k_out
450
+
451
+
452
+ def qkv_split_rope_kvcache_bf16(
453
+ packed_qkv: torch.Tensor,
454
+ rope: torch.Tensor,
455
+ q_heads: int,
456
+ kv_heads: int,
457
+ head_dim: int,
458
+ cache_offset: int,
459
+ q_out: torch.Tensor | None = None,
460
+ k_cache: torch.Tensor | None = None,
461
+ v_cache: torch.Tensor | None = None,
462
+ max_seq_len: int | None = None,
463
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
464
+ """Split GQA packed QKV, apply interleaved RoPE, and write K/V cache.
465
+
466
+ ``packed_qkv`` has shape ``(batch, seq_len, (q_heads + 2 * kv_heads) * head_dim)``.
467
+ ``rope`` has BF16 interleaved ``[cos0, sin0, cos1, sin1, ...]`` rows with
468
+ shape ``(>= seq_len, head_dim)``. ``q_out`` has shape
469
+ ``(batch, seq_len, q_heads, head_dim)``. K/V are written in-place into
470
+ ``(batch, max_seq_len, kv_heads, head_dim)`` caches starting at
471
+ ``cache_offset``.
472
+ """
473
+
474
+ batch, seq_len, _ = packed_qkv.shape
475
+ if q_out is None:
476
+ q_out = torch.empty(
477
+ (batch, seq_len, q_heads, head_dim),
478
+ device=packed_qkv.device,
479
+ dtype=torch.bfloat16,
480
+ )
481
+ if k_cache is None or v_cache is None:
482
+ if max_seq_len is None:
483
+ max_seq_len = cache_offset + seq_len
484
+ cache_shape = (batch, int(max_seq_len), kv_heads, head_dim)
485
+ if k_cache is None:
486
+ k_cache = torch.empty(cache_shape, device=packed_qkv.device, dtype=torch.bfloat16)
487
+ if v_cache is None:
488
+ v_cache = torch.empty(cache_shape, device=packed_qkv.device, dtype=torch.bfloat16)
489
+ ops.qkv_split_rope_kvcache_bf16(
490
+ packed_qkv,
491
+ rope,
492
+ int(q_heads),
493
+ int(kv_heads),
494
+ int(head_dim),
495
+ int(cache_offset),
496
+ q_out,
497
+ k_cache,
498
+ v_cache,
499
+ )
500
+ return q_out, k_cache, v_cache
501
+
502
+
503
+ def qkv_split_per_head_norm_rope_bf16(
504
+ packed_qkv: torch.Tensor,
505
+ q_norm_weight: torch.Tensor,
506
+ k_norm_weight: torch.Tensor,
507
+ cos: torch.Tensor,
508
+ sin: torch.Tensor,
509
+ q_heads: int,
510
+ kv_heads: int,
511
+ eps: float = 1e-6,
512
+ q_out: torch.Tensor | None = None,
513
+ k_out: torch.Tensor | None = None,
514
+ v_out: torch.Tensor | None = None,
515
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
516
+ """Split GQA QKV, apply per-head Q/K RMSNorm and half-rotation RoPE."""
517
+
518
+ batch, seq_len, _ = packed_qkv.shape
519
+ if q_out is None:
520
+ q_out = torch.empty(
521
+ (batch, seq_len, q_heads, 128),
522
+ device=packed_qkv.device,
523
+ dtype=torch.bfloat16,
524
+ )
525
+ if k_out is None:
526
+ k_out = torch.empty(
527
+ (batch, seq_len, kv_heads, 128),
528
+ device=packed_qkv.device,
529
+ dtype=torch.bfloat16,
530
+ )
531
+ if v_out is None:
532
+ v_out = torch.empty_like(k_out)
533
+ ops.qkv_split_per_head_norm_rope_bf16(
534
+ packed_qkv,
535
+ q_norm_weight,
536
+ k_norm_weight,
537
+ cos,
538
+ sin,
539
+ int(q_heads),
540
+ int(kv_heads),
541
+ float(eps),
542
+ q_out,
543
+ k_out,
544
+ v_out,
545
+ )
546
+ return q_out, k_out, v_out
547
+
548
+
549
+ def qkv_split_bias_rope_bf16(
550
+ packed_qkv: torch.Tensor,
551
+ qkv_bias: torch.Tensor,
552
+ cos: torch.Tensor,
553
+ sin: torch.Tensor,
554
+ q_heads: int,
555
+ kv_heads: int,
556
+ head_dim: int,
557
+ q_out: torch.Tensor | None = None,
558
+ k_out: torch.Tensor | None = None,
559
+ v_out: torch.Tensor | None = None,
560
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
561
+ """Add packed QKV bias, split Q/K/V, and apply split-half RoPE to Q/K."""
562
+
563
+ batch, seq_len, _ = packed_qkv.shape
564
+ if q_out is None:
565
+ q_out = torch.empty(
566
+ (batch, seq_len, q_heads, head_dim),
567
+ device=packed_qkv.device,
568
+ dtype=torch.bfloat16,
569
+ )
570
+ if k_out is None:
571
+ k_out = torch.empty(
572
+ (batch, seq_len, kv_heads, head_dim),
573
+ device=packed_qkv.device,
574
+ dtype=torch.bfloat16,
575
+ )
576
+ if v_out is None:
577
+ v_out = torch.empty_like(k_out)
578
+ ops.qkv_split_bias_rope_bf16(
579
+ packed_qkv,
580
+ qkv_bias,
581
+ cos,
582
+ sin,
583
+ int(q_heads),
584
+ int(kv_heads),
585
+ int(head_dim),
586
+ q_out,
587
+ k_out,
588
+ v_out,
589
+ )
590
+ return q_out, k_out, v_out
591
+
592
+
593
+ def qkv_split_bias_rope_fp16(
594
+ packed_qkv: torch.Tensor,
595
+ qkv_bias: torch.Tensor,
596
+ cos: torch.Tensor,
597
+ sin: torch.Tensor,
598
+ q_heads: int,
599
+ kv_heads: int,
600
+ head_dim: int,
601
+ q_out: torch.Tensor | None = None,
602
+ k_out: torch.Tensor | None = None,
603
+ v_out: torch.Tensor | None = None,
604
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
605
+ """Add bias, split packed QKV, apply RoPE, and emit FP16 attention inputs."""
606
+
607
+ batch, seq_len, _ = packed_qkv.shape
608
+ if q_out is None:
609
+ q_out = torch.empty(
610
+ (batch, seq_len, q_heads, head_dim),
611
+ device=packed_qkv.device,
612
+ dtype=torch.float16,
613
+ )
614
+ if k_out is None:
615
+ k_out = torch.empty(
616
+ (batch, seq_len, kv_heads, head_dim),
617
+ device=packed_qkv.device,
618
+ dtype=torch.float16,
619
+ )
620
+ if v_out is None:
621
+ v_out = torch.empty_like(k_out)
622
+ ops.qkv_split_bias_rope_fp16(
623
+ packed_qkv,
624
+ qkv_bias,
625
+ cos,
626
+ sin,
627
+ int(q_heads),
628
+ int(kv_heads),
629
+ int(head_dim),
630
+ q_out,
631
+ k_out,
632
+ v_out,
633
+ )
634
+ return q_out, k_out, v_out
635
+
636
+
637
+ def qkv_split_bf16(
638
+ packed_qkv: torch.Tensor,
639
+ heads: int,
640
+ head_dim: int,
641
+ q_out: torch.Tensor | None = None,
642
+ k_out: torch.Tensor | None = None,
643
+ v_out: torch.Tensor | None = None,
644
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
645
+ """Split packed BF16 QKV into Q/K/V tensors.
646
+
647
+ ``packed_qkv`` has shape ``(batch, seq_len, 3 * heads * head_dim)``.
648
+ Outputs have shape ``(batch, seq_len, heads, head_dim)``.
649
+ """
650
+
651
+ out_shape = (packed_qkv.shape[0], packed_qkv.shape[1], heads, head_dim)
652
+ if q_out is None:
653
+ q_out = torch.empty(out_shape, device=packed_qkv.device, dtype=torch.bfloat16)
654
+ if k_out is None:
655
+ k_out = torch.empty(out_shape, device=packed_qkv.device, dtype=torch.bfloat16)
656
+ if v_out is None:
657
+ v_out = torch.empty(out_shape, device=packed_qkv.device, dtype=torch.bfloat16)
658
+ ops.qkv_split_bf16(packed_qkv, int(heads), int(head_dim), q_out, k_out, v_out)
659
+ return q_out, k_out, v_out
660
+
661
+
662
+ def decode_q_norm_rope_stage_bf16(
663
+ q_pre: torch.Tensor,
664
+ q_norm_weight: torch.Tensor,
665
+ cos: torch.Tensor,
666
+ sin: torch.Tensor,
667
+ eps: float = 1e-6,
668
+ q_out: torch.Tensor | None = None,
669
+ ) -> torch.Tensor:
670
+ """RMSNorm Q, apply rotate-half RoPE, and write a decode Q staging buffer.
671
+
672
+ The decode path is fixed to ``head_dim == 128``. ``cos`` and ``sin`` have
673
+ shape ``(64,)`` and dtype BF16.
674
+ """
675
+
676
+ if q_out is None:
677
+ q_out = torch.empty_like(q_pre)
678
+ ops.decode_q_norm_rope_stage_bf16(
679
+ q_pre, q_norm_weight, cos, sin, float(eps), q_out
680
+ )
681
+ return q_out
682
+
683
+
684
+ def decode_k_norm_rope_kvwrite_bf16(
685
+ k_pre: torch.Tensor,
686
+ v_pre: torch.Tensor,
687
+ k_norm_weight: torch.Tensor,
688
+ cos: torch.Tensor,
689
+ sin: torch.Tensor,
690
+ eps: float = 1e-6,
691
+ k_cache_dst: torch.Tensor | None = None,
692
+ v_cache_dst: torch.Tensor | None = None,
693
+ ) -> tuple[torch.Tensor, torch.Tensor]:
694
+ """RMSNorm K, apply rotate-half RoPE, and write one KV cache slot."""
695
+
696
+ if k_cache_dst is None:
697
+ k_cache_dst = torch.empty_like(k_pre)
698
+ if v_cache_dst is None:
699
+ v_cache_dst = torch.empty_like(v_pre)
700
+ ops.decode_k_norm_rope_kvwrite_bf16(
701
+ k_pre, v_pre, k_norm_weight, cos, sin, float(eps), k_cache_dst, v_cache_dst
702
+ )
703
+ return k_cache_dst, v_cache_dst
704
+
705
+
706
+ def decode_k_norm_rope_kvwrite_devpos_bf16(
707
+ k_pre: torch.Tensor,
708
+ v_pre: torch.Tensor,
709
+ k_norm_weight: torch.Tensor,
710
+ cos: torch.Tensor,
711
+ sin: torch.Tensor,
712
+ cur_pos: torch.Tensor,
713
+ k_cache: torch.Tensor,
714
+ v_cache: torch.Tensor,
715
+ eps: float = 1e-6,
716
+ ) -> tuple[torch.Tensor, torch.Tensor]:
717
+ """Write one KV cache slot selected by device int32 ``cur_pos``."""
718
+
719
+ ops.decode_k_norm_rope_kvwrite_devpos_bf16(
720
+ k_pre, v_pre, k_norm_weight, cos, sin, cur_pos, float(eps), k_cache, v_cache
721
+ )
722
+ return k_cache, v_cache
723
+
724
+
725
+ def qkv_split_bias_norm_rope_v_bf16(
726
+ packed_qkv: torch.Tensor,
727
+ qkv_bias: torch.Tensor,
728
+ norm_q_weight: torch.Tensor,
729
+ norm_k_weight: torch.Tensor,
730
+ freqs_re: torch.Tensor,
731
+ freqs_im: torch.Tensor,
732
+ heads: int,
733
+ head_dim: int,
734
+ rope_seq_len: int | None = None,
735
+ eps: float = 1e-6,
736
+ q_out: torch.Tensor | None = None,
737
+ k_out: torch.Tensor | None = None,
738
+ v_out: torch.Tensor | None = None,
739
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
740
+ """Bias QKV, RMSNorm Q/K, apply RoPE, and materialize Q/K/V."""
741
+
742
+ if rope_seq_len is None:
743
+ rope_seq_len = packed_qkv.shape[1]
744
+ out_shape = (packed_qkv.shape[0], packed_qkv.shape[1], heads, head_dim)
745
+ if q_out is None:
746
+ q_out = torch.empty(out_shape, device=packed_qkv.device, dtype=torch.bfloat16)
747
+ if k_out is None:
748
+ k_out = torch.empty(out_shape, device=packed_qkv.device, dtype=torch.bfloat16)
749
+ if v_out is None:
750
+ v_out = torch.empty(out_shape, device=packed_qkv.device, dtype=torch.bfloat16)
751
+ ops.qkv_split_bias_norm_rope_v_bf16(
752
+ packed_qkv,
753
+ qkv_bias,
754
+ norm_q_weight,
755
+ norm_k_weight,
756
+ freqs_re,
757
+ freqs_im,
758
+ int(heads),
759
+ int(head_dim),
760
+ int(rope_seq_len),
761
+ float(eps),
762
+ q_out,
763
+ k_out,
764
+ v_out,
765
+ )
766
+ return q_out, k_out, v_out
767
+
768
+
769
+ def qkv_split_bias_norm_rope_v_cat_bf16(
770
+ packed_qkv: torch.Tensor,
771
+ qkv_bias: torch.Tensor,
772
+ norm_q_weight: torch.Tensor,
773
+ norm_k_weight: torch.Tensor,
774
+ freqs_re: torch.Tensor,
775
+ freqs_im: torch.Tensor,
776
+ heads: int,
777
+ head_dim: int,
778
+ video_offset: int,
779
+ q_cat_out: torch.Tensor,
780
+ k_cat_out: torch.Tensor,
781
+ v_cat_out: torch.Tensor,
782
+ rope_seq_len: int | None = None,
783
+ eps: float = 1e-6,
784
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
785
+ """Write a biased video QKV segment directly into joint Q/K/V workspaces."""
786
+
787
+ if rope_seq_len is None:
788
+ rope_seq_len = packed_qkv.shape[1]
789
+ ops.qkv_split_bias_norm_rope_v_cat_bf16(
790
+ packed_qkv,
791
+ qkv_bias,
792
+ norm_q_weight,
793
+ norm_k_weight,
794
+ freqs_re,
795
+ freqs_im,
796
+ int(heads),
797
+ int(head_dim),
798
+ int(video_offset),
799
+ int(rope_seq_len),
800
+ float(eps),
801
+ q_cat_out,
802
+ k_cat_out,
803
+ v_cat_out,
804
+ )
805
+ return q_cat_out, k_cat_out, v_cat_out
806
+
807
+
808
+ def qkv_split_joint3_cat_bf16(
809
+ packed_v: torch.Tensor,
810
+ qkv_v_bias: torch.Tensor,
811
+ norm_v_q_weight: torch.Tensor,
812
+ norm_v_k_weight: torch.Tensor,
813
+ freqs_re: torch.Tensor,
814
+ freqs_im: torch.Tensor,
815
+ packed_a: torch.Tensor,
816
+ norm_a_q_weight: torch.Tensor,
817
+ norm_a_k_weight: torch.Tensor,
818
+ packed_u: torch.Tensor,
819
+ norm_u_q_weight: torch.Tensor,
820
+ norm_u_k_weight: torch.Tensor,
821
+ heads: int,
822
+ head_dim: int,
823
+ q_cat_out: torch.Tensor,
824
+ k_cat_out: torch.Tensor,
825
+ v_cat_out: torch.Tensor,
826
+ rope_seq_len: int | None = None,
827
+ eps_v: float = 1e-6,
828
+ eps_a: float = 1e-6,
829
+ eps_u: float = 1e-6,
830
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
831
+ """Fuse video/action/und QKV postprocess into one joint Q/K/V workspace."""
832
+
833
+ if rope_seq_len is None:
834
+ rope_seq_len = packed_v.shape[1]
835
+ ops.qkv_split_joint3_cat_bf16(
836
+ packed_v,
837
+ qkv_v_bias,
838
+ norm_v_q_weight,
839
+ norm_v_k_weight,
840
+ freqs_re,
841
+ freqs_im,
842
+ packed_a,
843
+ norm_a_q_weight,
844
+ norm_a_k_weight,
845
+ packed_u,
846
+ norm_u_q_weight,
847
+ norm_u_k_weight,
848
+ int(heads),
849
+ int(head_dim),
850
+ int(rope_seq_len),
851
+ float(eps_v),
852
+ float(eps_a),
853
+ float(eps_u),
854
+ q_cat_out,
855
+ k_cat_out,
856
+ v_cat_out,
857
+ )
858
+ return q_cat_out, k_cat_out, v_cat_out
859
+
860
+
861
+ __all__ = [
862
+ "decode_q_norm_rope_stage_bf16",
863
+ "decode_k_norm_rope_kvwrite_bf16",
864
+ "decode_k_norm_rope_kvwrite_devpos_bf16",
865
+ "qkv_split_per_head_norm_rope_bf16",
866
+ "qkv_split_bias_rope_bf16",
867
+ "qkv_split_bias_rope_fp16",
868
+ "qkv_split_bf16",
869
+ "qkv_split_rope_kvcache_bf16",
870
+ "qkv_split_norm_rope_bf16",
871
+ "qkv_split_bias_norm_rope_v_bf16",
872
+ "qkv_split_bias_norm_rope_v_cat_bf16",
873
+ "qkv_split_joint3_cat_bf16",
874
+ ]
build/torch213-cxx11-cu130-aarch64-linux/_ops.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import flashrt_qkv_cache_rope_test
3
+ ops = torch.ops.flashrt_qkv_cache_rope_test
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ return f"flashrt_qkv_cache_rope_test::{op_name}"
build/torch213-cxx11-cu130-aarch64-linux/flashrt_qkv_cache_rope/__init__.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import importlib.util
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ def _import_from_path(file_path: Path):
7
+ path_hash = '{:x}'.format(ctypes.c_size_t(hash(file_path.absolute())).value)
8
+ spec = importlib.util.spec_from_file_location(path_hash, file_path)
9
+ module = importlib.util.module_from_spec(spec)
10
+ sys.modules[path_hash] = module
11
+ spec.loader.exec_module(module)
12
+ return module
13
+
14
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / '__init__.py')))
build/torch213-cxx11-cu130-aarch64-linux/flashrt_qkv_cache_rope_test.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:01f26796945d40568f3d97be10dd32f172154d8731f04bbb87931478fbbd0124
3
+ size 544152
build/torch213-cxx11-cu130-aarch64-linux/metadata.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "flashrt-qkv-cache-rope",
3
+ "id": "flashrt_qkv_cache_rope_test",
4
+ "version": 1,
5
+ "license": "Apache-2.0",
6
+ "python-depends": [],
7
+ "backend": {
8
+ "type": "cuda",
9
+ "archs": [
10
+ "11.0"
11
+ ]
12
+ },
13
+ "digest": {
14
+ "algorithm": "sha256",
15
+ "files": {
16
+ "__init__.py": "A5t1ELQb0pbOoFMjZR7VzYvIds3qUO94UZ/4ZbqHd6U=",
17
+ "flashrt_qkv_cache_rope_test.abi3.so": "AfJnlpRdQFaPPZe+EN0y8XIVTYcx8Eu7h5MUePu9ASQ=",
18
+ "_ops.py": "ZSIUGrzgBBffx37jx/znR0nnvtuaR3+G3FSvPKa9UHQ=",
19
+ "flashrt_qkv_cache_rope/__init__.py": "v6p5XMfQzddhi1fLSAw4HX9CyS0rQsidvu9VsT01xi4="
20
+ }
21
+ },
22
+ "provenance": {
23
+ "kernel": {
24
+ "sha": "456d297",
25
+ "dirty": false
26
+ },
27
+ "validation": {
28
+ "torch": "2.13.0+cu130",
29
+ "cuda": "13.0"
30
+ }
31
+ }
32
+ }