kernels-bot commited on
Commit
fbf55f6
·
verified ·
1 Parent(s): d91aa5e

Uploaded using `kernel-builder`.

Browse files
README.md CHANGED
@@ -30,6 +30,8 @@ matmul_2d(...)
30
  - `rms_norm_rows`
31
  - `swizzle_mx_scales`
32
  - `unswizzle_mx_scales`
 
 
33
  - `mxfp8_act_quant`
34
  - `mxfp4_act_quant`
35
  - `nvfp4_act_quant`
 
30
  - `rms_norm_rows`
31
  - `swizzle_mx_scales`
32
  - `unswizzle_mx_scales`
33
+ - `prepare_nvfp4_csf_scales`
34
+ - `decompress_nvfp4_csf_scales`
35
  - `mxfp8_act_quant`
36
  - `mxfp4_act_quant`
37
  - `nvfp4_act_quant`
build/torch-xpu/__init__.py CHANGED
@@ -22,6 +22,7 @@ from . import backward
22
  from .formats import get_supported_act_fns
23
  from .norm import get_supported_norms, rms_norm_rows
24
  from .swizzle import swizzle_mx_scales, unswizzle_mx_scales
 
25
  from .quant import mxfp4_act_quant, mxfp8_act_quant, nvfp4_act_quant
26
 
27
  __all__ = [
@@ -41,10 +42,13 @@ __all__ = [
41
  # the per-expert output norm a model can hand the forwards by name, and its standalone op
42
  "get_supported_norms",
43
  "rms_norm_rows",
44
- # load-time helpers: the swizzled scale layout the SM100 scaled-MMA reads, and the row-wise
45
- # quantizers a loader uses to quantize weights into the group formats
 
46
  "swizzle_mx_scales",
47
  "unswizzle_mx_scales",
 
 
48
  "mxfp8_act_quant",
49
  "mxfp4_act_quant",
50
  "nvfp4_act_quant",
 
22
  from .formats import get_supported_act_fns
23
  from .norm import get_supported_norms, rms_norm_rows
24
  from .swizzle import swizzle_mx_scales, unswizzle_mx_scales
25
+ from .loading.scales import prepare_nvfp4_csf_scales, decompress_nvfp4_csf_scales
26
  from .quant import mxfp4_act_quant, mxfp8_act_quant, nvfp4_act_quant
27
 
28
  __all__ = [
 
42
  # the per-expert output norm a model can hand the forwards by name, and its standalone op
43
  "get_supported_norms",
44
  "rms_norm_rows",
45
+ # load-time helpers: the swizzled scale layout the SM100 scaled-MMA reads, CSF scale-stream
46
+ # preparation/decoding, and the row-wise quantizers a loader uses to quantize weights into the
47
+ # group formats
48
  "swizzle_mx_scales",
49
  "unswizzle_mx_scales",
50
+ "prepare_nvfp4_csf_scales",
51
+ "decompress_nvfp4_csf_scales",
52
  "mxfp8_act_quant",
53
  "mxfp4_act_quant",
54
  "nvfp4_act_quant",
build/torch-xpu/_ops.py CHANGED
@@ -25,7 +25,7 @@ def get_backend() -> str:
25
 
26
  def _find_ops_name() -> str:
27
  kernel_name = "finegrained_kernels"
28
- unique_id = "78a2a29"
29
  backend = get_backend()
30
  return f"_{kernel_name}_{backend}_{unique_id}"
31
 
 
25
 
26
  def _find_ops_name() -> str:
27
  kernel_name = "finegrained_kernels"
28
+ unique_id = "bbd13a8"
29
  backend = get_backend()
30
  return f"_{kernel_name}_{backend}_{unique_id}"
31
 
build/torch-xpu/batched.py CHANGED
@@ -31,9 +31,9 @@ from .formats import check_activation_format, global_scale_stride, gate_out_cols
31
  from .epilogue import fused_glu
32
  from .quant import fp8_act_quant_block_dynamic, MX_ACT_QUANT, static_expert_act_operands, tensor_wide_act_operands
33
  from .swizzle import swizzled_scale_descriptor
34
- from .scheduling import is_off_rank
35
  from .mma import block_dynamic_dot, fp8_dot, mx_compute, mx_weight_only_compute, static_dot
36
- from .loading.scales import weight_scale_rows
37
  from .loading.tiles import (
38
  advance_ptrs,
39
  load_act_block_dynamic,
@@ -1788,6 +1788,8 @@ def matmul_batched(
1788
  scatter_idx: torch.Tensor | None = None,
1789
  a_global_scale: torch.Tensor | None = None,
1790
  b_global_scale: torch.Tensor | None = None,
 
 
1791
  output_global_scale: torch.Tensor | None = None,
1792
  ) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
1793
  """Batched matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4, or full-precision). Routes one
@@ -1825,7 +1827,15 @@ def matmul_batched(
1825
  - one scale per expert (``Bs`` ``(E,)``/``(E, 1, 1)``) →
1826
  ``w8a8_tensor_dynamic_fp8_matmul_batched``.
1827
  - block scales (``Bs`` ``(E, N/bn, K/bk)``) → ``w8a8_block_dynamic_fp8_matmul_batched``.
 
 
 
1828
  """
 
 
 
 
 
1829
  check_activation_format(activation_format, quantize_output)
1830
  assert act_fn is not None or not quantize_output, "the raw gate|up output (act_fn=None) is not requantized"
1831
  assert (a_global_scale is None and b_global_scale is None) or (
 
31
  from .epilogue import fused_glu
32
  from .quant import fp8_act_quant_block_dynamic, MX_ACT_QUANT, static_expert_act_operands, tensor_wide_act_operands
33
  from .swizzle import swizzled_scale_descriptor
34
+ from .scheduling import is_off_rank, routed_expert_start
35
  from .mma import block_dynamic_dot, fp8_dot, mx_compute, mx_weight_only_compute, static_dot
36
+ from .loading.scales import csf_weight_scales, weight_scale_rows
37
  from .loading.tiles import (
38
  advance_ptrs,
39
  load_act_block_dynamic,
 
1788
  scatter_idx: torch.Tensor | None = None,
1789
  a_global_scale: torch.Tensor | None = None,
1790
  b_global_scale: torch.Tensor | None = None,
1791
+ b_scale_exceptions: torch.Tensor | None = None,
1792
+ b_scale_exception_offsets: torch.Tensor | None = None,
1793
  output_global_scale: torch.Tensor | None = None,
1794
  ) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
1795
  """Batched matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4, or full-precision). Routes one
 
1827
  - one scale per expert (``Bs`` ``(E,)``/``(E, 1, 1)``) →
1828
  ``w8a8_tensor_dynamic_fp8_matmul_batched``.
1829
  - block scales (``Bs`` ``(E, N/bn, K/bk)``) → ``w8a8_block_dynamic_fp8_matmul_batched``.
1830
+ - CSF-compressed NVFP4 weight scales (``prepare_nvfp4_csf_scales``): ``Bs`` is the fixed
1831
+ stream, ``b_scale_exceptions``/``b_scale_exception_offsets`` its exceptions and expert
1832
+ offsets; the op decodes them before the GEMM (only the routed experts when routing allows).
1833
  """
1834
+ if b_scale_exceptions is not None:
1835
+ Bs = csf_weight_scales(
1836
+ Bs, b_scale_exceptions, b_scale_exception_offsets,
1837
+ routed_expert_start(expert_ids, B.shape[0]),
1838
+ )
1839
  check_activation_format(activation_format, quantize_output)
1840
  assert act_fn is not None or not quantize_output, "the raw gate|up output (act_fn=None) is not requantized"
1841
  assert (a_global_scale is None and b_global_scale is None) or (
build/torch-xpu/grouped.py CHANGED
@@ -30,6 +30,7 @@ from .quant import fp8_act_quant_block_dynamic, MX_ACT_QUANT, mx_act_quant_group
30
  from .swizzle import swizzled_scale_descriptor
31
  from .mma import block_dynamic_dot, fp8_dot, mx_compute, mx_weight_only_compute, static_dot
32
  from .scheduling import build_tile_layout, expand_gather_below_parity, expand_regime, build_packed_schedule, load_packed_schedule, prefetch_packed_entry, resolve_grouped_tile, resolve_grouped_tile_packed
 
33
  from .loading.tiles import (
34
  load_act_block_dynamic,
35
  load_act_mx,
@@ -2227,6 +2228,8 @@ def matmul_grouped(
2227
  scatter_idx: torch.Tensor | None = None,
2228
  a_global_scale: torch.Tensor | None = None,
2229
  b_global_scale: torch.Tensor | None = None,
 
 
2230
  output_global_scale: torch.Tensor | None = None,
2231
  ) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
2232
  """Grouped matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4, or full-precision).
@@ -2268,7 +2271,11 @@ def matmul_grouped(
2268
  - one scale per expert (``Bs`` ``(E,)``/``(E, 1, 1)``) →
2269
  ``w8a8_tensor_dynamic_fp8_matmul_grouped``.
2270
  - block scales (``Bs`` ``(E, N/bn, K/bk)``) → ``w8a8_block_dynamic_fp8_matmul_grouped``.
 
 
 
2271
  """
 
2272
  check_activation_format(activation_format, quantize_output)
2273
  assert act_fn is not None or not quantize_output, "the raw gate|up output (act_fn=None) is not requantized"
2274
  if gather_idx is not None and activation_format == "bf16" and As is None:
 
30
  from .swizzle import swizzled_scale_descriptor
31
  from .mma import block_dynamic_dot, fp8_dot, mx_compute, mx_weight_only_compute, static_dot
32
  from .scheduling import build_tile_layout, expand_gather_below_parity, expand_regime, build_packed_schedule, load_packed_schedule, prefetch_packed_entry, resolve_grouped_tile, resolve_grouped_tile_packed
33
+ from .loading.scales import csf_weight_scales
34
  from .loading.tiles import (
35
  load_act_block_dynamic,
36
  load_act_mx,
 
2228
  scatter_idx: torch.Tensor | None = None,
2229
  a_global_scale: torch.Tensor | None = None,
2230
  b_global_scale: torch.Tensor | None = None,
2231
+ b_scale_exceptions: torch.Tensor | None = None,
2232
+ b_scale_exception_offsets: torch.Tensor | None = None,
2233
  output_global_scale: torch.Tensor | None = None,
2234
  ) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
2235
  """Grouped matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4, or full-precision).
 
2271
  - one scale per expert (``Bs`` ``(E,)``/``(E, 1, 1)``) →
2272
  ``w8a8_tensor_dynamic_fp8_matmul_grouped``.
2273
  - block scales (``Bs`` ``(E, N/bn, K/bk)``) → ``w8a8_block_dynamic_fp8_matmul_grouped``.
2274
+ - CSF-compressed NVFP4 weight scales (``prepare_nvfp4_csf_scales``): ``Bs`` is the fixed
2275
+ stream, ``b_scale_exceptions``/``b_scale_exception_offsets`` its exceptions and expert
2276
+ offsets; the op decodes them before the GEMM (only the routed experts when routing allows).
2277
  """
2278
+ Bs = csf_weight_scales(Bs, b_scale_exceptions, b_scale_exception_offsets, expert_start)
2279
  check_activation_format(activation_format, quantize_output)
2280
  assert act_fn is not None or not quantize_output, "the raw gate|up output (act_fn=None) is not requantized"
2281
  if gather_idx is not None and activation_format == "bf16" and As is None:
build/torch-xpu/loading/scales.py CHANGED
@@ -12,9 +12,16 @@
12
  # See the License for the specific language governing permissions and
13
  # limitations under the License.
14
 
 
 
 
15
  import triton
16
  import triton.language as tl
17
 
 
 
 
 
18
  from ..quant import fp8_act_quant_inline, mx_act_quant_inline
19
 
20
 
@@ -337,3 +344,259 @@ def mx_2d_scale_ptrs(
337
  as_mask = offs_am_lin < M
338
  bs_mask = offs_bn_lin < (2 * N if GATE else N)
339
  return as_ptrs, bs_ptrs, as_mask, bs_mask
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  # See the License for the specific language governing permissions and
13
  # limitations under the License.
14
 
15
+ from collections.abc import Sequence
16
+
17
+ import torch
18
  import triton
19
  import triton.language as tl
20
 
21
+ from ..compat import (
22
+ add_op_namespace_prefix, compile_time_only_triton_op, compile_time_only_triton_wrap,
23
+ device_context, sm_count,
24
+ )
25
  from ..quant import fp8_act_quant_inline, mx_act_quant_inline
26
 
27
 
 
344
  as_mask = offs_am_lin < M
345
  bs_mask = offs_bn_lin < (2 * N if GATE else N)
346
  return as_ptrs, bs_ptrs, as_mask, bs_mask
347
+
348
+
349
+ # CSF byte-window scales: stream preparation and staged decoding before ordinary GEMMs.
350
+
351
+
352
+ def prepare_nvfp4_csf_scales(
353
+ fixed: torch.Tensor, exceptions: torch.Tensor | Sequence[torch.Tensor]
354
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
355
+ """Prepare one matrix or an expert stack without expanding or moving its scales.
356
+
357
+ CSF stores each row of E4M3 scale bytes as a base plus 4-bit deltas, which is
358
+ lossless whenever a row's bytes span at most 16 codes; the rest are exceptions.
359
+
360
+ - `fixed` is uint8 `[rows/16, 16*(1+cols/2)]`, or the same shape with a leading
361
+ expert dimension. Each 16-row slab holds 16 row bases (bytes 0..240), then those
362
+ rows' deltas, two per byte (even column in the low nibble). Scale `(r, c)` decodes
363
+ to byte `base[r] + delta[r, c]`.
364
+ - `exceptions` is one uint32 `[count]` tensor for a matrix, or one per expert, for
365
+ the scales outside their row's window. Each word is `position | byte << 24`:
366
+ the low 24 bits are the row-major index `r * cols + c` (sorted and unique), the
367
+ high 8 bits are the exact E4M3 byte, which overwrites the decoded value.
368
+
369
+ Returns, on the input device:
370
+
371
+ - `fixed`: contiguous `[experts, rows/16, 16*(1+cols/2)]` (a 2D input gains `experts=1`).
372
+ - `exceptions`: every expert's words concatenated into one uint32 vector.
373
+ - `expert_offsets`: uint32 `[experts + 1]` prefix sums; expert `e` owns
374
+ `exceptions[expert_offsets[e]:expert_offsets[e + 1]]`.
375
+
376
+ These are `decompress_nvfp4_csf_scales`' inputs. Decode on the accelerator at load time
377
+ for dense residency, or into shared scratch immediately before GEMM. The checks here
378
+ run once per checkpoint load, off the forward path, so the decoder does not repeat them.
379
+ """
380
+ if fixed.dtype != torch.uint8 or fixed.ndim not in (2, 3):
381
+ raise ValueError("CSF fixed stream must be a 2D or 3D uint8 tensor")
382
+ fixed = fixed.unsqueeze(0) if fixed.ndim == 2 else fixed
383
+ experts, slabs, slab_bytes = fixed.shape
384
+ if experts == 0 or slabs == 0 or slab_bytes <= 16 or slab_bytes % 16:
385
+ raise ValueError("Invalid CSF slab shape")
386
+ rows, cols = slabs * 16, (slab_bytes // 16 - 1) * 2
387
+ if rows * cols > 1 << 24:
388
+ raise ValueError(
389
+ "CSF exception positions support at most 2**24 scales per matrix"
390
+ )
391
+ if bool((fixed[:, :, :16] > 240).any()):
392
+ raise ValueError("CSF row bases must be in 0..240")
393
+ streams = [exceptions] if isinstance(exceptions, torch.Tensor) else list(exceptions)
394
+ if len(streams) != experts:
395
+ raise ValueError("CSF needs one exception stream per expert")
396
+ offsets, words = [0], []
397
+ for stream in streams:
398
+ if (
399
+ stream.dtype != torch.uint32
400
+ or stream.ndim != 1
401
+ or stream.device != fixed.device
402
+ ):
403
+ raise ValueError(
404
+ "CSF exception streams must be 1D uint32 tensors on the fixed stream's device"
405
+ )
406
+ values = stream.to(torch.int64)
407
+ positions = values & 0xFFFFFF
408
+ if positions.numel() and (
409
+ int(positions[-1]) >= rows * cols
410
+ or bool((positions[1:] <= positions[:-1]).any())
411
+ ):
412
+ raise ValueError(
413
+ "CSF exception positions must be sorted, unique and in range"
414
+ )
415
+ offsets.append(offsets[-1] + stream.numel())
416
+ words.append(stream)
417
+ if offsets[-1] >= 1 << 32:
418
+ raise ValueError("CSF exception directory exceeds uint32 offsets")
419
+ return (
420
+ fixed.contiguous(),
421
+ torch.cat(words),
422
+ torch.tensor(offsets, dtype=torch.uint32, device=fixed.device),
423
+ )
424
+
425
+
426
+ @triton.jit
427
+ def _decode_fixed_kernel(
428
+ Fixed,
429
+ Out,
430
+ ExpertStart,
431
+ E: tl.constexpr,
432
+ ROWS: tl.constexpr,
433
+ COLS: tl.constexpr,
434
+ BLOCK: tl.constexpr,
435
+ ALIGNED_OUTPUT: tl.constexpr,
436
+ ):
437
+ pairs: tl.constexpr = ROWS * (COLS // 2)
438
+ tiles: tl.constexpr = tl.cdiv(pairs, BLOCK)
439
+ offsets = tl.arange(0, BLOCK)
440
+ # Contiguous pairs avoid padding each row to a power-of-two tile width.
441
+ # Keep indices local to an expert; only the expert base needs 64-bit addressing.
442
+ for tile in range(tl.program_id(0), E * tiles, tl.num_programs(0)):
443
+ expert = tile // tiles
444
+ active = True
445
+ if ExpertStart is not None:
446
+ active = tl.load(ExpertStart + expert + 1) > tl.load(ExpertStart + expert)
447
+ if active:
448
+ pair = (tile % tiles) * BLOCK + offsets
449
+ row = pair // (COLS // 2)
450
+ slab = expert.to(tl.int64) * (ROWS // 16) + row // 16
451
+ slab_bytes: tl.constexpr = 16 * (1 + COLS // 2)
452
+ base = tl.load(Fixed + slab * slab_bytes + row % 16, pair < pairs, other=0).to(
453
+ tl.uint16
454
+ )
455
+ packed = tl.load(
456
+ Fixed + slab * slab_bytes + 16 + (row % 16) * (COLS // 2) + pair % (COLS // 2),
457
+ pair < pairs,
458
+ other=0,
459
+ ).to(tl.uint16)
460
+ low = base + (packed & 15)
461
+ high = base + (packed >> 4)
462
+ # A contiguous sliced workspace can start at an odd byte.
463
+ if ALIGNED_OUTPUT:
464
+ output = Out.to(tl.pointer_type(tl.uint16))
465
+ tl.store(
466
+ output + expert.to(tl.int64) * pairs + pair,
467
+ low | (high << 8),
468
+ pair < pairs,
469
+ )
470
+ else:
471
+ values = tl.interleave(low, high).to(tl.uint8).to(tl.float8e4nv, bitcast=True)
472
+ output_offsets = (tile % tiles) * BLOCK * 2 + tl.arange(0, BLOCK * 2)
473
+ tl.store(
474
+ Out + expert.to(tl.int64) * pairs * 2 + output_offsets,
475
+ values,
476
+ output_offsets < pairs * 2,
477
+ )
478
+
479
+
480
+ @triton.jit
481
+ def _apply_exceptions_kernel(
482
+ Exceptions,
483
+ ExpertOffsets,
484
+ Out,
485
+ ExpertStart,
486
+ PLANE: tl.constexpr,
487
+ BLOCK: tl.constexpr,
488
+ ):
489
+ expert = tl.program_id(0)
490
+ if ExpertStart is not None:
491
+ if tl.load(ExpertStart + expert + 1) == tl.load(ExpertStart + expert):
492
+ return
493
+ start = tl.load(ExpertOffsets + expert).to(tl.int64)
494
+ end = tl.load(ExpertOffsets + expert + 1).to(tl.int64)
495
+ for base in range(start, end, BLOCK):
496
+ index = base + tl.arange(0, BLOCK)
497
+ word = tl.load(Exceptions + index, index < end, other=0)
498
+ position = word & 0xFFFFFF
499
+ value = (word >> 24).to(tl.uint8).to(tl.float8e4nv, bitcast=True)
500
+ tl.store(Out + expert.to(tl.int64) * PLANE + position, value, index < end)
501
+
502
+
503
+ @compile_time_only_triton_op(
504
+ add_op_namespace_prefix("decompress_nvfp4_csf_scales_into"),
505
+ mutates_args={"out"},
506
+ opaque=True,
507
+ )
508
+ def _decompress_into(
509
+ fixed: torch.Tensor,
510
+ exceptions: torch.Tensor,
511
+ expert_offsets: torch.Tensor,
512
+ out: torch.Tensor,
513
+ expert_start: torch.Tensor | None,
514
+ ) -> None:
515
+ experts, rows, cols = out.shape
516
+ with device_context(fixed.device):
517
+ programs = min(
518
+ experts * triton.cdiv(rows * cols // 2, 4096),
519
+ 16 * sm_count(fixed.device.index),
520
+ )
521
+ compile_time_only_triton_wrap(_decode_fixed_kernel)[(programs,)](
522
+ fixed,
523
+ out,
524
+ expert_start,
525
+ experts,
526
+ rows,
527
+ cols,
528
+ 4096,
529
+ ALIGNED_OUTPUT=out.storage_offset() % 2 == 0,
530
+ )
531
+ # The fixed stream decodes every scale branch-free as base + delta, including the
532
+ # few outside their row's 16-code window. This second, small pass overwrites those
533
+ # positions with their exact bytes (stream order runs after the first kernel).
534
+ if exceptions.numel():
535
+ compile_time_only_triton_wrap(_apply_exceptions_kernel)[(experts,)](
536
+ exceptions, expert_offsets, out, expert_start, rows * cols, 256
537
+ )
538
+
539
+
540
+ def decompress_nvfp4_csf_scales(
541
+ fixed: torch.Tensor,
542
+ exceptions: torch.Tensor,
543
+ expert_offsets: torch.Tensor,
544
+ *,
545
+ out: torch.Tensor | None = None,
546
+ expert_start: torch.Tensor | None = None,
547
+ ) -> torch.Tensor:
548
+ """Decode prepared CSF streams to dense E4M3 scales for an ordinary NVFP4 GEMM.
549
+
550
+ With no `out`, allocate dense scales on the accelerator at checkpoint loading.
551
+ Pass reusable contiguous [experts, rows, cols] workspace to keep the streams
552
+ compressed between layers. Consume the workspace before overwriting it; it
553
+ must not be retained for backward or shared by concurrent consumers.
554
+ A shared dense workspace saves memory across layers, not within one layer.
555
+ Pass the grouped GEMM's cumulative `expert_start` to decode only experts with
556
+ routed tokens. Inactive workspace planes stay untouched and must not be read.
557
+
558
+ The streams must come from `prepare_nvfp4_csf_scales`, which validates them; only
559
+ `out` and `expert_start`, which are new here, are checked.
560
+ """
561
+ if fixed.device.type == "cpu":
562
+ raise ValueError("CSF decompression requires an accelerator")
563
+ experts, slabs, slab_bytes = fixed.shape
564
+ rows, cols = slabs * 16, (slab_bytes // 16 - 1) * 2
565
+ shape = (experts, rows, cols)
566
+ if out is None:
567
+ out = torch.empty(shape, dtype=torch.float8_e4m3fn, device=fixed.device)
568
+ if (
569
+ out.shape != shape
570
+ or out.dtype != torch.float8_e4m3fn
571
+ or not out.is_contiguous()
572
+ ):
573
+ raise ValueError(f"CSF workspace must be contiguous E4M3 with shape {shape}")
574
+ if any(t.device != out.device for t in (fixed, exceptions, expert_offsets)):
575
+ raise ValueError("CSF buffers and workspace must share a device")
576
+ if expert_start is not None and (
577
+ expert_start.shape != (experts + 1,)
578
+ or expert_start.dtype not in (torch.int32, torch.int64)
579
+ or not expert_start.is_contiguous()
580
+ or expert_start.device != out.device
581
+ ):
582
+ raise ValueError("CSF expert_start must be a contiguous device int32/int64 vector of length experts + 1")
583
+ _decompress_into(fixed, exceptions, expert_offsets, out, expert_start)
584
+ return out
585
+
586
+
587
+ def csf_weight_scales(
588
+ scales: torch.Tensor | None,
589
+ exceptions: torch.Tensor | None,
590
+ exception_offsets: torch.Tensor | None,
591
+ expert_start: torch.Tensor | None = None,
592
+ ) -> torch.Tensor | None:
593
+ """A public op's weight scales: with ``exceptions`` given, ``scales`` is the prepared CSF fixed
594
+ stream and decodes here (only the experts with routed rows when ``expert_start`` is given) into
595
+ a fresh dense E4M3 buffer. The caching allocator recycles that buffer across calls and layers,
596
+ so callers keep only the compressed streams resident. Dense scales pass through."""
597
+ if exceptions is None:
598
+ return scales
599
+ return decompress_nvfp4_csf_scales(
600
+ scales, exceptions, exception_offsets, expert_start=expert_start
601
+ )
602
+
build/torch-xpu/matmul.py CHANGED
@@ -27,7 +27,7 @@ from .descriptors import maybe_descriptor, rebind_bd_descriptors, rebind_mx_desc
27
  from .formats import check_activation_format, global_scale_stride, gate_out_cols, normalize_global_scale, e2m1_as_uint8, is_mx, mx_scale_family, resolve_activation_format, resolve_output_dtype, ue8m0_as_uint8, validate_dense_2d_operands, weight_format
28
  from .swizzle import swizzle_mx_scales, swizzled_scale_descriptor
29
  from .quant import MX_ACT_QUANT, fp8_act_quant_block_dynamic, maybe_act_quant, mxfp8_act_quant, nvfp4_act_quant, quantize_rows_static, tensor_wide_act_operands
30
- from .loading.scales import apply_global_scale, mx_2d_scale_ptrs, weight_scale_rows
31
  from .mma import block_dynamic_dot, fp8_dot, mx_compute, mx_weight_only_compute, static_dot
32
  from .loading.tiles import (
33
  advance_ptrs,
@@ -1912,6 +1912,8 @@ def matmul_2d(
1912
  output_dtype: torch.dtype | None = None,
1913
  a_global_scale: torch.Tensor | None = None,
1914
  b_global_scale: torch.Tensor | None = None,
 
 
1915
  output_global_scale: torch.Tensor | None = None,
1916
  ) -> torch.Tensor | list[torch.Tensor]:
1917
  """Dense (2D) quantized matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4) — the single-GEMM sibling of
@@ -1937,11 +1939,18 @@ def matmul_2d(
1937
  ``[..., N]`` intermediate (``act_fn=None``: the raw ``[..., 2N]`` gate|up output instead); ``quantize_output=True`` (MX weights only) stores that intermediate in
1938
  ``activation_format`` and returns ``(C, Cs)`` for the next op.
1939
 
1940
- Routes by weight dtype + inferred block: ``Bs`` None → full-precision; MX/NVFP4 (int8/E4M3 weights
1941
- with UE8M0 group-32 or E4M3 group-16 ``Bs``) → ``mx_dynamic_matmul``; tensor-wide FP8 (scalar
1942
- ``Bs``) → ``w8a8_tensor_dynamic_fp8_matmul``; block FP8 → the static variant when ``As`` is a
1943
- per-tensor scalar, else dynamic.
 
 
 
 
 
1944
  """
 
 
1945
  check_activation_format(activation_format, quantize_output)
1946
  assert act_fn is not None or not quantize_output, "the raw gate|up output (act_fn=None) is not requantized"
1947
  assert (a_global_scale is None and b_global_scale is None) or (
 
27
  from .formats import check_activation_format, global_scale_stride, gate_out_cols, normalize_global_scale, e2m1_as_uint8, is_mx, mx_scale_family, resolve_activation_format, resolve_output_dtype, ue8m0_as_uint8, validate_dense_2d_operands, weight_format
28
  from .swizzle import swizzle_mx_scales, swizzled_scale_descriptor
29
  from .quant import MX_ACT_QUANT, fp8_act_quant_block_dynamic, maybe_act_quant, mxfp8_act_quant, nvfp4_act_quant, quantize_rows_static, tensor_wide_act_operands
30
+ from .loading.scales import apply_global_scale, csf_weight_scales, mx_2d_scale_ptrs, weight_scale_rows
31
  from .mma import block_dynamic_dot, fp8_dot, mx_compute, mx_weight_only_compute, static_dot
32
  from .loading.tiles import (
33
  advance_ptrs,
 
1912
  output_dtype: torch.dtype | None = None,
1913
  a_global_scale: torch.Tensor | None = None,
1914
  b_global_scale: torch.Tensor | None = None,
1915
+ b_scale_exceptions: torch.Tensor | None = None,
1916
+ b_scale_exception_offsets: torch.Tensor | None = None,
1917
  output_global_scale: torch.Tensor | None = None,
1918
  ) -> torch.Tensor | list[torch.Tensor]:
1919
  """Dense (2D) quantized matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4) — the single-GEMM sibling of
 
1939
  ``[..., N]`` intermediate (``act_fn=None``: the raw ``[..., 2N]`` gate|up output instead); ``quantize_output=True`` (MX weights only) stores that intermediate in
1940
  ``activation_format`` and returns ``(C, Cs)`` for the next op.
1941
 
1942
+ Routes by weight dtype + inferred block:
1943
+ - ``Bs`` None → full-precision.
1944
+ - MX/NVFP4 (int8/E4M3 weights with UE8M0 group-32 or E4M3 group-16 ``Bs``) →
1945
+ ``mx_dynamic_matmul``.
1946
+ - tensor-wide FP8 (scalar ``Bs``) → ``w8a8_tensor_dynamic_fp8_matmul``.
1947
+ - block FP8 → the static variant when ``As`` is a per-tensor scalar, else dynamic.
1948
+ - CSF-compressed NVFP4 weight scales (``prepare_nvfp4_csf_scales``): ``Bs`` is the fixed
1949
+ stream, ``b_scale_exceptions``/``b_scale_exception_offsets`` its exceptions and expert
1950
+ offsets; the op decodes them before the GEMM.
1951
  """
1952
+ if b_scale_exceptions is not None: # one prepared matrix decodes as a 1-expert stack
1953
+ Bs = csf_weight_scales(Bs, b_scale_exceptions, b_scale_exception_offsets)[0]
1954
  check_activation_format(activation_format, quantize_output)
1955
  assert act_fn is not None or not quantize_output, "the raw gate|up output (act_fn=None) is not requantized"
1956
  assert (a_global_scale is None and b_global_scale is None) or (
build/torch-xpu/metadata.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "name": "finegrained-kernels",
3
- "id": "_finegrained_kernels_xpu_78a2a29",
4
  "version": 0,
5
  "kernels-minver": "0.14.0",
6
  "license": "Apache-2.0",
@@ -12,30 +12,30 @@
12
  "digest": {
13
  "algorithm": "sha256",
14
  "files": {
15
- "__init__.py": "xFRwaLTont8ZLTxS5ajuiDqM9gWwXAU4xap2prqdhrY=",
16
- "_ops.py": "6ajnsgIjvPzGZBsQyo6hy2ukYkhjeD9B6q+AogINgPY=",
17
  "autotune_config.py": "d5fb2Vqss0fgC9TZbarrmQIInL1n1L7rHz6o3Gqv6cI=",
18
  "backward.py": "K1S6KD3J/12SthXiqBcmNO9kUikctQpccsbxsO8lpRg=",
19
- "batched.py": "EA/eS6jhAvLinodFgT6A6Mz5hWJQjIwOrKvFWUMgz7c=",
20
  "bayesian_autotuner.py": "NDRUQrhk+bEEvrOkIilWJPfqdKpcsd4E4QQ9AHzylKI=",
21
  "compat.py": "K3RCq1ETi80duzv3zSldIwrL5e46vZAWtLxLlg1LXvM=",
22
  "descriptors.py": "4acRMazGPFlbydNt1Hbo8RpAqb3fOtnOQBv5yb4onqw=",
23
  "embedding.py": "k7jiz2vtEJuYKo+w6TuS/4WO1D4Bv96O5DMFjEpYUGo=",
24
  "epilogue.py": "AmE9Mhs0iWhnS5CneW3XGkg2Vvrj7+Ej2RmoorIM5gs=",
25
  "formats.py": "TT9zs05HzUMOVF5DG1OTRg8AjXssXHGoJoRONRJSyrg=",
26
- "grouped.py": "sNQ5L3DzTk6BFMyiCWbbkIwAWX2VEAG3SEpE+2gKHAQ=",
27
  "loading/__init__.py": "so7kYmlVoiASfoOzemdU5fBTiP8yA85gVPNQExIq/KU=",
28
- "loading/scales.py": "tcenA3+yIqrfCMttlMJNWgGJDUIwWWpUGltox6qaRxQ=",
29
  "loading/tiles.py": "p1go4zzcZ6nog6JCXgNbjFyhp5cL8iu6Is96gUV4+ks=",
30
- "matmul.py": "GFc0Olq/UV3xLJxuYuQNEGvbVL8TJ9oGbWFCKqjBUM8=",
31
  "mma.py": "gLkCU5QjhQVMacixNR24Yi07aNelQyN+I0pJOuRxE4E=",
32
- "moe.py": "kmGfWaq+hx++ri1Xt1X2aIuafGM96zOK4EDAO9n+Jyw=",
33
  "norm.py": "VvE6GUE0Oztf7PDcviLCcB4fhnXt7/zgdE+aApv6DBM=",
34
  "pruners.py": "AWpe/H5N3mXQnqxsU9AMkX8KPbwJ5qo4vu+fCM/KFlE=",
35
  "quant.py": "1fNRvb63DAOcFNLfKw3cSwMqSwLua4smI+xvhlsUk3k=",
36
- "scheduling.py": "cxwoL5NTJxARVxLStDsNalm/jqbkCObm8uyLRFL/yYc=",
37
  "swizzle.py": "ueIJ9FsO8QZhVt3nMFlA+8b+U9/ZHabHFlhufsONV04=",
38
- "symbols.json": "wHUHJ8vYH5uj+XDbZv4GynNezpqBAuAVg5r4/l35UsA="
39
  }
40
  },
41
  "provenance": {
@@ -45,7 +45,7 @@
45
  "dirty": false
46
  },
47
  "kernel": {
48
- "commit": "78a2a29b886fcaaa5ee6a8cda4cbadf28e622a37",
49
  "dirty": false
50
  }
51
  }
 
1
  {
2
  "name": "finegrained-kernels",
3
+ "id": "_finegrained_kernels_xpu_bbd13a8",
4
  "version": 0,
5
  "kernels-minver": "0.14.0",
6
  "license": "Apache-2.0",
 
12
  "digest": {
13
  "algorithm": "sha256",
14
  "files": {
15
+ "__init__.py": "YGdTqU34klTI43VQVxTlk3qo0iJPSFaECyKN7nbwgqM=",
16
+ "_ops.py": "A9CLOqiJNpGlsP+gfdW8KzwepufQlyrG2qGK1YRVoog=",
17
  "autotune_config.py": "d5fb2Vqss0fgC9TZbarrmQIInL1n1L7rHz6o3Gqv6cI=",
18
  "backward.py": "K1S6KD3J/12SthXiqBcmNO9kUikctQpccsbxsO8lpRg=",
19
+ "batched.py": "R6swbEtGGx/h+766rP4wsSsfmr4KfYzRF0cq7goLcyI=",
20
  "bayesian_autotuner.py": "NDRUQrhk+bEEvrOkIilWJPfqdKpcsd4E4QQ9AHzylKI=",
21
  "compat.py": "K3RCq1ETi80duzv3zSldIwrL5e46vZAWtLxLlg1LXvM=",
22
  "descriptors.py": "4acRMazGPFlbydNt1Hbo8RpAqb3fOtnOQBv5yb4onqw=",
23
  "embedding.py": "k7jiz2vtEJuYKo+w6TuS/4WO1D4Bv96O5DMFjEpYUGo=",
24
  "epilogue.py": "AmE9Mhs0iWhnS5CneW3XGkg2Vvrj7+Ej2RmoorIM5gs=",
25
  "formats.py": "TT9zs05HzUMOVF5DG1OTRg8AjXssXHGoJoRONRJSyrg=",
26
+ "grouped.py": "5F+eYL+8eSr3BVRwX9R3d3HhmvKj4YdVw6u3W6MlNWg=",
27
  "loading/__init__.py": "so7kYmlVoiASfoOzemdU5fBTiP8yA85gVPNQExIq/KU=",
28
+ "loading/scales.py": "Ywe/tL94/S2YQI2T/d0ywfEUAkSYVpQTxpzGlb4cu9A=",
29
  "loading/tiles.py": "p1go4zzcZ6nog6JCXgNbjFyhp5cL8iu6Is96gUV4+ks=",
30
+ "matmul.py": "TdCy8rzuCtYEzowgQiPzbaFXAqANzUxuG62d6ZEYc0g=",
31
  "mma.py": "gLkCU5QjhQVMacixNR24Yi07aNelQyN+I0pJOuRxE4E=",
32
+ "moe.py": "9X93HFPen8gm7cB66X9EIxnOxGAmF4o1SBcBAZ6h+sE=",
33
  "norm.py": "VvE6GUE0Oztf7PDcviLCcB4fhnXt7/zgdE+aApv6DBM=",
34
  "pruners.py": "AWpe/H5N3mXQnqxsU9AMkX8KPbwJ5qo4vu+fCM/KFlE=",
35
  "quant.py": "1fNRvb63DAOcFNLfKw3cSwMqSwLua4smI+xvhlsUk3k=",
36
+ "scheduling.py": "A67jzd628qAVOqthPsRQQqbLfBybsZzOMO1e7wmZyT0=",
37
  "swizzle.py": "ueIJ9FsO8QZhVt3nMFlA+8b+U9/ZHabHFlhufsONV04=",
38
+ "symbols.json": "49uaUpO+Ntuu6o54Da6UAHvpFY9MgyjV/seN/pk8KlI="
39
  }
40
  },
41
  "provenance": {
 
45
  "dirty": false
46
  },
47
  "kernel": {
48
+ "commit": "bbd13a828401b2fc6232fb13ccc122b0d3442fc5",
49
  "dirty": false
50
  }
51
  }
build/torch-xpu/metadata.json.sigstore CHANGED
@@ -1 +1 @@
1
- {"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial":{"certificate":{"rawBytes":"MIIHLTCCBrOgAwIBAgIUaJFSxhpSWMO+Yia4J1eh8hBr+R0wCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYxMDIwMTMxNTU5WhcNMjYxMDIwMTMyNTU5WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWt0ciJhHthUmSorEYVFfA9osevZEL54NMFNHGraSNn8VcvFNeOL2M9+LKrahPxsmsuwl0u3lcxKCtdKhoqmcrKOCBdIwggXOMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAfBgNVHSMEGDAWgBTf0+nPViQRlvmo2OkoVaLGLhhkPzBrBgNVHREBAf8EYTBfhl1odHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkvLmdpdGh1Yi93b3JrZmxvd3MvYnVpbGQueWFtbEByZWZzL2hlYWRzL21haW4wOQYKKwYBBAGDvzABAQQraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTAfBgorBgEEAYO/MAECBBF3b3JrZmxvd19kaXNwYXRjaDA2BgorBgEEAYO/MAEDBCg3OGEyYTI5Yjg4NmZjYWFhNWVlNmE4Y2RhNGNiYWRmMjhlNjIyYTM3MBMGCisGAQQBg78wAQQEBUJ1aWxkMCsGCisGAQQBg78wAQUEHWh1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjA7BgorBgEEAYO/MAEIBC0MK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wbQYKKwYBBAGDvzABCQRfDF1odHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkvLmdpdGh1Yi93b3JrZmxvd3MvYnVpbGQueWFtbEByZWZzL2hlYWRzL21haW4wOAYKKwYBBAGDvzABCgQqDCg3OGEyYTI5Yjg4NmZjYWFhNWVlNmE4Y2RhNGNiYWRmMjhlNjIyYTM3MBsGCisGAQQBg78wAQsEDQwLc2VsZi1ob3N0ZWQwQAYKKwYBBAGDvzABDAQyDDBodHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkwOAYKKwYBBAGDvzABDQQqDCg3OGEyYTI5Yjg4NmZjYWFhNWVlNmE4Y2RhNGNiYWRmMjhlNjIyYTM3MB8GCisGAQQBg78wAQ4EEQwPcmVmcy9oZWFkcy9tYWluMBoGCisGAQQBg78wAQ8EDAwKMTA3MTQ3NTUyOTAuBgorBgEEAYO/MAEQBCAMHmh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZTAYBgorBgEEAYO/MAERBAoMCDI1NzIwNzQzMG0GCisGAQQBg78wARIEXwxdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wARMEKgwoNzhhMmEyOWI4ODZmY2FhYTVlZTZhOGNkYTRjYmFkZjI4ZTYyMmEzNzAhBgorBgEEAYO/MAEUBBMMEXdvcmtmbG93X2Rpc3BhdGNoMGQGCisGAQQBg78wARUEVgxUaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5L2FjdGlvbnMvcnVucy8zOTQyODI2MzM5My9hdHRlbXB0cy8xMBYGCisGAQQBg78wARYECAwGcHVibGljMEYGCisGAQQBg78wARgEOAw2cmVwbzpodWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eTpyZWY6cmVmcy9oZWFkcy9tYWluMIGLBgorBgEEAdZ5AgQCBH0EewB5AHcA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGhWXRZDAAABAMASDBGAiEA4kZJuKrCfhK+U2gZyDuFFQdDzpYkksvJQQ5Oi3N1l0YCIQDM+Br8zIDbZyQuT4pwho2jHSiSaDMgxjSp4evZhVWnBzAKBggqhkjOPQQDAwNoADBlAjEAzxxTvKkxYWujsdRVN16qq9u9FFrMWBuN0Ft70vFcDaHYokP8/1DtU6kUJyP8OkZmAjATzE+uSBijKKOFUipYtktXOV5Om7S0VgcA8zpEvhJTUdQZ9n5YifVl41u7dNhskds="}, "tlogEntries":[{"logIndex":"3337654267", "logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion":{"kind":"hashedrekord", "version":"0.0.1"}, "integratedTime":"1792502159", "inclusionPromise":{"signedEntryTimestamp":"MEUCIBDRBfn0OEr/3FI257Q8J6VNl0wPOC4C9GtEHCLvNMTiAiEAnA1frW7ZaIw2jb3g+xvOtbVeES3WKa4S0gjEkCnqI6s="}, "inclusionProof":{"logIndex":"3215750005", "rootHash":"EpuX/pRAzmWjhxJJhokpLRrLM4SW3jmWkE5KChIWqqs=", "treeSize":"3215750022", "hashes":["+ZeLGpISpSAYliOcVIzDBZa7/lRtEiq0zYgusOE8i1M=", "bTc4oPq97OYTzCwCBDAdAPlPOzw4/tVYm6M5A2Wv3Yk=", "0Xs6asm0G6/DH7iTugZlSR07Imsx+672Wz5bMCB7h2U=", "reyrj33h3Dm3n+/sj7mWmRDYNL6sZZpBbYnYKs03u3k=", "RJx/cVf+3XKI/JqI1krMKi6OZW7LQW+zgfDdarPNl4I=", "9/LkgO5mZRBXdGtH+UTxlIc5W1oBba0dcd9HRKcRnxs=", "LHM96E7LWMo97lKFxzwhu+bu4iqAgL9T08PQziX/ILw=", "BvQoQxsxgHD/VUQH9EPYOE3ZPJFndtBpjVYPSNDrKkM=", "27lVQFnJ0RKrJBEQGk4oUznEo3pFrggEC9gXDrQPiec=", "kys4WGMTuPqGaZc79EMJO/inn7y58MLx7inDyoMzO7I=", "kOrL2VZ9Dyg9SYQbyjbCK6l98qmY0xZiHeM68R2bcj8=", "sV2HYjtjXhxymU+V7/5mR942xjHqAOkHVQC7t+zu2us=", "XailVEBW00TuSppkvc+4KYSUGmNa81YudM5FIt3nvSE=", "zK7qW++aMer3MkBNGlcXVS4wV7x70Epwzh1KB82PWiQ=", "wc+TLATo5lnmbuwIr4/sQmH0osErTOAAiMahYD4f4sE=", "HxMxUZSh35Y+k1xWQyJAxe5BvkFVx4UmVeFrI31tchA=", "6Rb7uOgk2v5YKcFSbAPOpLlWAIN1ciDPdlp4J/CUu5k=", "HovTPBWzoErvUg1u5sIi3x1ZonZ7yJekVsBrmpomCIA=", "G+nk7mgE5h6dUmv2UY7NDJrY3WvrZY31raaO1AETt+o=", "qlTWNDzERnTBQVcHHXXVPjiUP0SsikGxfcxVlgqVFDo=", "gg9GNApNke3+zNhl4tsWtmIycCFrOMCB3lys6XuSQNQ=", "NlOclldmKPA1tMKIskqHAwuQDYHp31YwpK+OOMrMccc=", "qxzHanAzz57SDdmJe0B7bJK72NTIBbwEMGBBKvDOROw=", "xH/DCseLHr9eKoYT8qsORZK7zVdEGYWHuVtsVrD95wY="], "checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n3215750022\nEpuX/pRAzmWjhxJJhokpLRrLM4SW3jmWkE5KChIWqqs=\n\n— rekor.sigstore.dev wNI9ajBFAiEAq2OMQrs8uxumi2h0nA5ZrHtYbTWATE2oUPVNlEPL++YCIDyHeEb1qqierZe6+ZukfeIOtSSZn9JBOILcjnoPz4AG\n"}}, "canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI5ZjRhNGU4YmUxYzQ5OWMxOTJlMWRiZDVkMDczYmE1NTJhMDZiZmMxMDRhNjA2MTRmZmUwNDVjZWMxZDU5MDg5In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUNWTnNNL3JRTHFoeUVZcXBIZVdtWHRBRWdzcUNGc0NtT3JXRW0rT2IwYmdBSWdFb3hlU3pXM0ZzL280ZXRLZTZKS3JZeDBvaEluRHRLQmxoYkNBV2s0ZlBRPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaE1WRU5EUW5KUFowRjNTVUpCWjBsVllVcEdVM2hvY0ZOWFRVOHJXV2xoTkVveFpXZzRhRUp5SzFJd2QwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFplRTFFU1hkTlZFMTRUbFJWTlZkb1kwNU5hbGw0VFVSSmQwMVVUWGxPVkZVMVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZYZERCamFVcG9TSFJvVlcxVGIzSkZXVlpHWmtFNWIzTmxkbHBGVERVMFRrMUdUa2dLUjNKaFUwNXVPRlpqZGtaT1pVOU1NazA1SzB4TGNtRm9VSGh6YlhOMWQyd3dkVE5zWTNoTFEzUmtTMmh2Y1cxamNrdFBRMEprU1hkbloxaFBUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXWkNaMDVXU0ZOTlJVZEVRVmRuUWxSbUNqQXJibEJXYVZGU2JIWnRiekpQYTI5V1lVeEhUR2hvYTFCNlFuSkNaMDVXU0ZKRlFrRm1PRVZaVkVKbWFHd3hiMlJJVW5kamVtOTJUREprY0dSSGFERUtXV2sxYW1JeU1IWmhTRlp1V2pKc2RWb3lXbWhaTWxWMllUSldlV0p0Vm5OamVURnFZakl4ZEdSWE5YQmtTR3QyVEcxa2NHUkhhREZaYVRrellqTktjZ3BhYlhoMlpETk5kbGx1Vm5CaVIxRjFaVmRHZEdKRlFubGFWMXA2VERKb2JGbFhVbnBNTWpGb1lWYzBkMDlSV1V0TGQxbENRa0ZIUkhaNlFVSkJVVkZ5Q21GSVVqQmpTRTAyVEhrNU1HSXlkR3hpYVRWb1dUTlNjR0l5TlhwTWJXUndaRWRvTVZsdVZucGFXRXBxWWpJMU1GcFhOVEJNYlU1MllsUkJaa0puYjNJS1FtZEZSVUZaVHk5TlFVVkRRa0pHTTJJelNuSmFiWGgyWkRFNWEyRllUbmRaV0ZKcVlVUkJNa0puYjNKQ1owVkZRVmxQTDAxQlJVUkNRMmN6VDBkRmVRcFpWRWsxV1dwbk5FNXRXbXBaVjBab1RsZFdiRTV0UlRSWk1sSm9Ua2RPYVZsWFVtMU5hbWhzVG1wSmVWbFVUVE5OUWsxSFEybHpSMEZSVVVKbk56aDNDa0ZSVVVWQ1ZVb3hZVmQ0YTAxRGMwZERhWE5IUVZGUlFtYzNPSGRCVVZWRlNGZG9NVm95WkhCaWJXUnRXVmRPYkV3eWRHeGpiVFZzWWtoTmRGa3lPWFFLWWxoV2RXRllValZOUWpCSFEybHpSMEZSVVVKbk56aDNRVkZaUlVRelNteGFiazEyWVVkV2FGcElUWFppVjBad1ltcEJOMEpuYjNKQ1owVkZRVmxQTHdwTlFVVkpRa013VFVzeWFEQmtTRUo2VDJrNGRtUkhPWEphVnpSMVdWZE9NR0ZYT1hWamVUVnVZVmhTYjJSWFNqRmpNbFo1V1RJNWRXUkhWblZrUXpWcUNtSXlNSGRpVVZsTFMzZFpRa0pCUjBSMmVrRkNRMUZTWmtSR01XOWtTRkozWTNwdmRrd3laSEJrUjJneFdXazFhbUl5TUhaaFNGWnVXakpzZFZveVdtZ0tXVEpWZG1FeVZubGliVlp6WTNreGFtSXlNWFJrVnpWd1pFaHJka3h0WkhCa1IyZ3hXV2s1TTJJelNuSmFiWGgyWkROTmRsbHVWbkJpUjFGMVpWZEdkQXBpUlVKNVdsZGFla3d5YUd4WlYxSjZUREl4YUdGWE5IZFBRVmxMUzNkWlFrSkJSMFIyZWtGQ1EyZFJjVVJEWnpOUFIwVjVXVlJKTlZscVp6Uk9iVnBxQ2xsWFJtaE9WMVpzVG0xRk5Ga3lVbWhPUjA1cFdWZFNiVTFxYUd4T2FrbDVXVlJOTTAxQ2MwZERhWE5IUVZGUlFtYzNPSGRCVVhORlJGRjNUR015Vm5NS1dta3hiMkl6VGpCYVYxRjNVVUZaUzB0M1dVSkNRVWRFZG5wQlFrUkJVWGxFUkVKdlpFaFNkMk42YjNaTU1tUndaRWRvTVZscE5XcGlNakIyWVVoV2JncGFNbXgxV2pKYWFGa3lWWFpoTWxaNVltMVdjMk41TVdwaU1qRjBaRmMxY0dSSWEzZFBRVmxMUzNkWlFrSkJSMFIyZWtGQ1JGRlJjVVJEWnpOUFIwVjVDbGxVU1RWWmFtYzBUbTFhYWxsWFJtaE9WMVpzVG0xRk5Ga3lVbWhPUjA1cFdWZFNiVTFxYUd4T2FrbDVXVlJOTTAxQ09FZERhWE5IUVZGUlFtYzNPSGNLUVZFMFJVVlJkMUJqYlZadFkzazViMXBYUm10amVUbDBXVmRzZFUxQ2IwZERhWE5IUVZGUlFtYzNPSGRCVVRoRlJFRjNTMDFVUVROTlZGRXpUbFJWZVFwUFZFRjFRbWR2Y2tKblJVVkJXVTh2VFVGRlVVSkRRVTFJYldnd1pFaENlazlwT0haYU1td3dZVWhXYVV4dFRuWmlVemx2WkZka2JtRlhOVzVhYlVacUNscFVRVmxDWjI5eVFtZEZSVUZaVHk5TlFVVlNRa0Z2VFVORVNURk9la2wzVG5wUmVrMUhNRWREYVhOSFFWRlJRbWMzT0hkQlVrbEZXSGQ0WkdGSVVqQUtZMGhOTmt4NU9XNWhXRkp2WkZkSmRWa3lPWFJNTW1neFdqSmtjR0p0WkcxWlYwNXNUREowYkdOdE5XeGlTRTEwV1RJNWRHSllWblZoV0ZJMVRIazFiZ3BoV0ZKdlpGZEpkbVF5T1hsaE1scHpZak5rZWt3eVNqRmhWM2hyVEc1c2FHSlhlRUZqYlZadFkzazViMXBYUm10amVUbDBXVmRzZFUxRVowZERhWE5IQ2tGUlVVSm5OemgzUVZKTlJVdG5kMjlPZW1ob1RXMUZlVTlYU1RSUFJGcHRXVEpHYUZsVVZteGFWRnBvVDBkT2ExbFVVbXBaYlVacldtcEpORnBVV1hrS1RXMUZlazU2UVdoQ1oyOXlRbWRGUlVGWlR5OU5RVVZWUWtKTlRVVllaSFpqYlhSdFlrYzVNMWd5VW5Cak0wSm9aRWRPYjAxSFVVZERhWE5IUVZGUlFncG5OemgzUVZKVlJWWm5lRlZoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NbWd4V2pKa2NHSnRaRzFaVjA1c1RESjBiR050Tld4aVNFMTBDbGt5T1hSaVdGWjFZVmhTTlV3eVJtcGtSMngyWW01TmRtTnVWblZqZVRoNlQxUlJlVTlFU1RKTmVrMDFUWGs1YUdSSVVteGlXRUl3WTNrNGVFMUNXVWNLUTJselIwRlJVVUpuTnpoM1FWSlpSVU5CZDBkalNGWnBZa2RzYWsxRldVZERhWE5IUVZGUlFtYzNPSGRCVW1kRlQwRjNNbU50Vm5kaWVuQnZaRmRrYmdwaFZ6VnVXbTFHYWxwVE9YSmFXRXAxV2xkNGVreFhUblppVnpFeFltMXNNR1ZVY0hsYVYxazJZMjFXYldONU9XOWFWMFpyWTNrNWRGbFhiSFZOU1VkTUNrSm5iM0pDWjBWRlFXUmFOVUZuVVVOQ1NEQkZaWGRDTlVGSVkwRXpWREIzWVhOaVNFVlVTbXBIVWpSamJWZGpNMEZ4U2t0WWNtcGxVRXN6TDJnMGNIa0taME00Y0Rkdk5FRkJRVWRvVjFoU1drUkJRVUZDUVUxQlUwUkNSMEZwUlVFMGExcEtkVXR5UTJab1N5dFZNbWRhZVVSMVJrWlJaRVI2Y0ZscmEzTjJTZ3BSVVRWUGFUTk9NV3d3V1VOSlVVUk5LMEp5T0hwSlJHSmFlVkYxVkRSd2QyaHZNbXBJVTJsVFlVUk5aM2hxVTNBMFpYWmFhRlpYYmtKNlFVdENaMmR4Q21ocmFrOVFVVkZFUVhkT2IwRkVRbXhCYWtWQmVuaDRWSFpMYTNoWlYzVnFjMlJTVms0eE5uRnhPWFU1UmtaeVRWZENkVTR3Um5RM01IWkdZMFJoU0ZrS2IydFFPQzh4UkhSVk5tdFZTbmxRT0U5cldtMUJha0ZVZWtVcmRWTkNhV3BMUzA5R1ZXbHdXWFJyZEZoUFZqVlBiVGRUTUZablkwRTRlbkJGZG1oS1ZBcFZaRkZhT1c0MVdXbG1WbXcwTVhVM1pFNW9jMnRrY3owS0xTMHRMUzFGVGtRZ1EwVlNWRWxHU1VOQlZFVXRMUzB0TFFvPSJ9fX19"}], "timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyzADAgEAMIICwgYJKoZIhvcNAQcCoIICszCCAq8CAQMxDTALBglghkgBZQMEAgEwgbgGCyqGSIb3DQEJEAEEoIGoBIGlMIGiAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgGvvpyM5daNrIiQ9KigW43lvD1woe+c5H7EvPv83/0KoCFQD3L1oK+wRy6+QrK/QSKMNEGRsNihgPMjAyNjEwMjAxMzE1NTlaMAMCAQGgMqQwMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhoAAxggHcMIIB2AIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MTAyMDEzMTU1OVowLwYJKoZIhvcNAQkEMSIEINyAkk8G8TfnuJF2m0ryaVdbp85BgA5mEd3C4/QuT0sMMIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCCF+Se8B6tiysO0Q1bBDvyBssaIP9p6uebYcNnROs0FtzBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQ6E1QvDJBh7rzBQy/Lio6LKiOLDDAKBggqhkjOPQQDAgRoMGYCMQCFPPrAYXsCL4pef9zarV04KhKP9RSFgnvoqbDig1IrdvGpytpT4hGVzQEV3zEWLSgCMQD84JuotindjTYofPx8aHpL1yG50cu1URXGLfjdP8M+i47x/8ztaAJY3noPr9t9zzE="}]}}, "messageSignature":{"messageDigest":{"algorithm":"SHA2_256", "digest":"n0pOi+HEmcGS4dvV0HO6VSoGv8EEpgYU/+BFzsHVkIk="}, "signature":"MEUCIQCVNsM/rQLqhyEYqpHeWmXtAEgsqCFsCmOrWEm+Ob0bgAIgEoxeSzW3Fs/o4etKe6JKrYx0ohInDtKBlhbCAWk4fPQ="}}
 
1
+ {"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial":{"certificate":{"rawBytes":"MIIHKzCCBrKgAwIBAgIUHC8wcl1kX/JbMbKiE4FVYO+prL8wCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYxMDIwMTUxMDQwWhcNMjYxMDIwMTUyMDQwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsQRLUB6xoFYle2fcSUsPjnEcCgZmLp9bz2P/5j0EQp46NcS5Y2UddimgWh/Ip1oF4Zepi60nKaK6Lz0rRTiCRqOCBdEwggXNMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAfBgNVHSMEGDAWgBTf0+nPViQRlvmo2OkoVaLGLhhkPzBrBgNVHREBAf8EYTBfhl1odHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkvLmdpdGh1Yi93b3JrZmxvd3MvYnVpbGQueWFtbEByZWZzL2hlYWRzL21haW4wOQYKKwYBBAGDvzABAQQraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTAfBgorBgEEAYO/MAECBBF3b3JrZmxvd19kaXNwYXRjaDA2BgorBgEEAYO/MAEDBChiYmQxM2E4Mjg0MDFiMmZjNjIzMmZiMTNjY2MxMjJiMGQzNDQyZmM1MBMGCisGAQQBg78wAQQEBUJ1aWxkMCsGCisGAQQBg78wAQUEHWh1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5MB0GCisGAQQBg78wAQYED3JlZnMvaGVhZHMvbWFpbjA7BgorBgEEAYO/MAEIBC0MK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wbQYKKwYBBAGDvzABCQRfDF1odHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkvLmdpdGh1Yi93b3JrZmxvd3MvYnVpbGQueWFtbEByZWZzL2hlYWRzL21haW4wOAYKKwYBBAGDvzABCgQqDChiYmQxM2E4Mjg0MDFiMmZjNjIzMmZiMTNjY2MxMjJiMGQzNDQyZmM1MBsGCisGAQQBg78wAQsEDQwLc2VsZi1ob3N0ZWQwQAYKKwYBBAGDvzABDAQyDDBodHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHkwOAYKKwYBBAGDvzABDQQqDChiYmQxM2E4Mjg0MDFiMmZjNjIzMmZiMTNjY2MxMjJiMGQzNDQyZmM1MB8GCisGAQQBg78wAQ4EEQwPcmVmcy9oZWFkcy9tYWluMBoGCisGAQQBg78wAQ8EDAwKMTA3MTQ3NTUyOTAuBgorBgEEAYO/MAEQBCAMHmh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZTAYBgorBgEEAYO/MAERBAoMCDI1NzIwNzQzMG0GCisGAQQBg78wARIEXwxdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wARMEKgwoYmJkMTNhODI4NDAxYjJmYzYyMzJmYjEzY2NjMTIyYjBkMzQ0MmZjNTAhBgorBgEEAYO/MAEUBBMMEXdvcmtmbG93X2Rpc3BhdGNoMGQGCisGAQQBg78wARUEVgxUaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5L2FjdGlvbnMvcnVucy8zOTQ0NTI1MTI3My9hdHRlbXB0cy8xMBYGCisGAQQBg78wARYECAwGcHVibGljMEYGCisGAQQBg78wARgEOAw2cmVwbzpodWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eTpyZWY6cmVmcy9oZWFkcy9tYWluMIGKBgorBgEEAdZ5AgQCBHwEegB4AHYA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGhWd1ZQQAABAMARzBFAiAHypITgd6CL+AzKRIiyXZbN8RJQggLIhzqSO4CVV9xbwIhAPtbH3/e4kudi0vclPLu2lu8bJitW8nWdh0hKIuWxZe0MAoGCCqGSM49BAMDA2cAMGQCMFs+unF1TyFOoXIcBvSskpYRG8e4CldJD4Gt1YlVO/ssvGyiDJF5uRDrOxJCLX6M+QIwLaEYxRj2nI7caflU2T8sLAmBqZhZMlxClfIqry2w1//2R9SqqKNsQGy/594prJOD"}, "tlogEntries":[{"logIndex":"3339130426", "logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion":{"kind":"hashedrekord", "version":"0.0.1"}, "integratedTime":"1792509041", "inclusionPromise":{"signedEntryTimestamp":"MEYCIQCvyujPC0C5/M5HySh4ke5DSmM05dlGmXdqKnY3R51RJwIhAIeOpUMWWZmVeFfbti/ubzk+v9AYz518in38Z97187jh"}, "inclusionProof":{"logIndex":"3217226164", "rootHash":"aAfmDK/36rgiINi+u3H43jsdR+KvBbhhl0Nc0r2I9vQ=", "treeSize":"3217226274", "hashes":["ca5GNalktTsbGurshy30GhzGIP6QDbSSc6K35t2YdKQ=", "tNeFN0AKToulcumZEd+LgxYyuo5Px6DJMPZR8u5NEOw=", "iuAmI+PATWE4twmkvPDrSb9TWpfs+p9SUt6E1ZMOwHM=", "ehzDMfhx2swpET186mXA9gC2zZhApiyG0dB9i2UYw+Y=", "2Oryv3UdAONZselufvuadwJTSQyCZPhkxX5U3A4wFxY=", "DlFBBDkOhxmAmp8EZEwOdsg8PI+V/KLQr8qTu6uX81c=", "nhXquwdTMVAMDps1UKG2FEQt0npG20a+lqdGUM9PQuQ=", "8k4n9R6Kw6arfKtVv1/fuqlusNDOMFt9XEAU/VsBzAg=", "ihjw7czfJ6AUHTN3VRWC7CZIu8lz90V6ecA5BCETGxQ=", "yad744SnxxtV0Yyd6qv47P5yFF+UFzYSVmN+mh8jtVc=", "09pyo+G5mF68+pa7t1psiPGzJhglifTSaw9CbIKMqMU=", "aPYknwzqrIDM5LVynpVZH33H93HdgyR50BOomht+QP8=", "0RgfIOKppEB265lEdj/u+COTsb06TcDX0G42G5Lwe7o=", "dabD48Wgka/nV9/Ur20Wl2IqgXu7sesULelMO7ruTBk=", "blZpLEAd3NmIOAwBvBlK4Ldv3f/OCZsIFySRzXPzpAM=", "bb50n/N0zb4c/IMphDa1DnrDkBgUgubxyoMvGlURzSs=", "XqpeS/BHHOExU96Hvg5L+dHwq0RPJDHCmKTx/jXAg50=", "6Rb7uOgk2v5YKcFSbAPOpLlWAIN1ciDPdlp4J/CUu5k=", "HovTPBWzoErvUg1u5sIi3x1ZonZ7yJekVsBrmpomCIA=", "G+nk7mgE5h6dUmv2UY7NDJrY3WvrZY31raaO1AETt+o=", "qlTWNDzERnTBQVcHHXXVPjiUP0SsikGxfcxVlgqVFDo=", "gg9GNApNke3+zNhl4tsWtmIycCFrOMCB3lys6XuSQNQ=", "NlOclldmKPA1tMKIskqHAwuQDYHp31YwpK+OOMrMccc=", "qxzHanAzz57SDdmJe0B7bJK72NTIBbwEMGBBKvDOROw=", "xH/DCseLHr9eKoYT8qsORZK7zVdEGYWHuVtsVrD95wY="], "checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n3217226274\naAfmDK/36rgiINi+u3H43jsdR+KvBbhhl0Nc0r2I9vQ=\n\n— rekor.sigstore.dev wNI9ajBEAiB/ah2bQraH05wHYTAzmTtOS/3rOKjmWrjiBU5D2VY/swIgWud4RW8qpqy3L/uGRPONDi7UIPFrrCPEdZVa4jRs+IU=\n"}}, "canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIwOTk0YTYzNDAwNjM3NTFmMjQ0ZThkMmM2OTIxNzNkMzNmNGYwOTMyYTk1ODg1ZDJkYzBmN2Y5YTYwNTUyNjUwIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJSHhvWUcxeklPcldWK1ppL0l2NGdXT3pxWmxUV3dWU29xVWozSWxweERyd0FpQjc4VlFLNDRrM2VBQlVIMUc2WStVOFBzdE1NcWt6K1k0MlFFdDNNUkV6S1E9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaExla05EUW5KTFowRjNTVUpCWjBsVlNFTTRkMk5zTVd0WUwwcGlUV0pMYVVVMFJsWlpUeXR3Y2t3NGQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFplRTFFU1hkTlZGVjRUVVJSZDFkb1kwNU5hbGw0VFVSSmQwMVVWWGxOUkZGM1YycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZ6VVZKTVZVSTJlRzlHV1d4bE1tWmpVMVZ6VUdwdVJXTkRaMXB0VEhBNVlub3lVQzhLTldvd1JWRndORFpPWTFNMVdUSlZaR1JwYldkWGFDOUpjREZ2UmpSYVpYQnBOakJ1UzJGTE5reDZNSEpTVkdsRFVuRlBRMEprUlhkbloxaE9UVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXWkNaMDVXU0ZOTlJVZEVRVmRuUWxSbUNqQXJibEJXYVZGU2JIWnRiekpQYTI5V1lVeEhUR2hvYTFCNlFuSkNaMDVXU0ZKRlFrRm1PRVZaVkVKbWFHd3hiMlJJVW5kamVtOTJUREprY0dSSGFERUtXV2sxYW1JeU1IWmhTRlp1V2pKc2RWb3lXbWhaTWxWMllUSldlV0p0Vm5OamVURnFZakl4ZEdSWE5YQmtTR3QyVEcxa2NHUkhhREZaYVRrellqTktjZ3BhYlhoMlpETk5kbGx1Vm5CaVIxRjFaVmRHZEdKRlFubGFWMXA2VERKb2JGbFhVbnBNTWpGb1lWYzBkMDlSV1V0TGQxbENRa0ZIUkhaNlFVSkJVVkZ5Q21GSVVqQmpTRTAyVEhrNU1HSXlkR3hpYVRWb1dUTlNjR0l5TlhwTWJXUndaRWRvTVZsdVZucGFXRXBxWWpJMU1GcFhOVEJNYlU1MllsUkJaa0puYjNJS1FtZEZSVUZaVHk5TlFVVkRRa0pHTTJJelNuSmFiWGgyWkRFNWEyRllUbmRaV0ZKcVlVUkJNa0puYjNKQ1owVkZRVmxQTDAxQlJVUkNRMmhwV1cxUmVBcE5Na1UwVFdwbk1FMUVSbWxOYlZwcVRtcEplazF0V21sTlZFNXFXVEpOZUUxcVNtbE5SMUY2VGtSUmVWcHRUVEZOUWsxSFEybHpSMEZSVVVKbk56aDNDa0ZSVVVWQ1ZVb3hZVmQ0YTAxRGMwZERhWE5IUVZGUlFtYzNPSGRCVVZWRlNGZG9NVm95WkhCaWJXUnRXVmRPYkV3eWRHeGpiVFZzWWtoTmRGa3lPWFFLWWxoV2RXRllValZOUWpCSFEybHpSMEZSVVVKbk56aDNRVkZaUlVRelNteGFiazEyWVVkV2FGcElUWFppVjBad1ltcEJOMEpuYjNKQ1owVkZRVmxQTHdwTlFVVkpRa013VFVzeWFEQmtTRUo2VDJrNGRtUkhPWEphVnpSMVdWZE9NR0ZYT1hWamVUVnVZVmhTYjJSWFNqRmpNbFo1V1RJNWRXUkhWblZrUXpWcUNtSXlNSGRpVVZsTFMzZFpRa0pCUjBSMmVrRkNRMUZTWmtSR01XOWtTRkozWTNwdmRrd3laSEJrUjJneFdXazFhbUl5TUhaaFNGWnVXakpzZFZveVdtZ0tXVEpWZG1FeVZubGliVlp6WTNreGFtSXlNWFJrVnpWd1pFaHJka3h0WkhCa1IyZ3hXV2s1TTJJelNuSmFiWGgyWkROTmRsbHVWbkJpUjFGMVpWZEdkQXBpUlVKNVdsZGFla3d5YUd4WlYxSjZUREl4YUdGWE5IZFBRVmxMUzNkWlFrSkJSMFIyZWtGQ1EyZFJjVVJEYUdsWmJWRjRUVEpGTkUxcVp6Qk5SRVpwQ2sxdFdtcE9ha2w2VFcxYWFVMVVUbXBaTWsxNFRXcEthVTFIVVhwT1JGRjVXbTFOTVUxQ2MwZERhWE5IUVZGUlFtYzNPSGRCVVhORlJGRjNUR015Vm5NS1dta3hiMkl6VGpCYVYxRjNVVUZaUzB0M1dVSkNRVWRFZG5wQlFrUkJVWGxFUkVKdlpFaFNkMk42YjNaTU1tUndaRWRvTVZscE5XcGlNakIyWVVoV2JncGFNbXgxV2pKYWFGa3lWWFpoTWxaNVltMVdjMk41TVdwaU1qRjBaRmMxY0dSSWEzZFBRVmxMUzNkWlFrSkJSMFIyZWtGQ1JGRlJjVVJEYUdsWmJWRjRDazB5UlRSTmFtY3dUVVJHYVUxdFdtcE9ha2w2VFcxYWFVMVVUbXBaTWsxNFRXcEthVTFIVVhwT1JGRjVXbTFOTVUxQ09FZERhWE5IUVZGUlFtYzNPSGNLUVZFMFJVVlJkMUJqYlZadFkzazViMXBYUm10amVUbDBXVmRzZFUxQ2IwZERhWE5IUVZGUlFtYzNPSGRCVVRoRlJFRjNTMDFVUVROTlZGRXpUbFJWZVFwUFZFRjFRbWR2Y2tKblJVVkJXVTh2VFVGRlVVSkRRVTFJYldnd1pFaENlazlwT0haYU1td3dZVWhXYVV4dFRuWmlVemx2WkZka2JtRlhOVzVhYlVacUNscFVRVmxDWjI5eVFtZEZSVUZaVHk5TlFVVlNRa0Z2VFVORVNURk9la2wzVG5wUmVrMUhNRWREYVhOSFFWRlJRbWMzT0hkQlVrbEZXSGQ0WkdGSVVqQUtZMGhOTmt4NU9XNWhXRkp2WkZkSmRWa3lPWFJNTW1neFdqSmtjR0p0WkcxWlYwNXNUREowYkdOdE5XeGlTRTEwV1RJNWRHSllWblZoV0ZJMVRIazFiZ3BoV0ZKdlpGZEpkbVF5T1hsaE1scHpZak5rZWt3eVNqRmhWM2hyVEc1c2FHSlhlRUZqYlZadFkzazViMXBYUm10amVUbDBXVmRzZFUxRVowZERhWE5IQ2tGUlVVSm5OemgzUVZKTlJVdG5kMjlaYlVwclRWUk9hRTlFU1RST1JFRjRXV3BLYlZsNldYbE5la3B0V1dwRmVsa3lUbXBOVkVsNVdXcENhMDE2VVRBS1RXMWFhazVVUVdoQ1oyOXlRbWRGUlVGWlR5OU5RVVZWUWtKTlRVVllaSFpqYlhSdFlrYzVNMWd5VW5Cak0wSm9aRWRPYjAxSFVVZERhWE5IUVZGUlFncG5OemgzUVZKVlJWWm5lRlZoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NbWd4V2pKa2NHSnRaRzFaVjA1c1RESjBiR050Tld4aVNFMTBDbGt5T1hSaVdGWjFZVmhTTlV3eVJtcGtSMngyWW01TmRtTnVWblZqZVRoNlQxUlJNRTVVU1RGTlZFa3pUWGs1YUdSSVVteGlXRUl3WTNrNGVFMUNXVWNLUTJselIwRlJVVUpuTnpoM1FWSlpSVU5CZDBkalNGWnBZa2RzYWsxRldVZERhWE5IUVZGUlFtYzNPSGRCVW1kRlQwRjNNbU50Vm5kaWVuQnZaRmRrYmdwaFZ6VnVXbTFHYWxwVE9YSmFXRXAxV2xkNGVreFhUblppVnpFeFltMXNNR1ZVY0hsYVYxazJZMjFXYldONU9XOWFWMFpyWTNrNWRGbFhiSFZOU1VkTENrSm5iM0pDWjBWRlFXUmFOVUZuVVVOQ1NIZEZaV2RDTkVGSVdVRXpWREIzWVhOaVNFVlVTbXBIVWpSamJWZGpNMEZ4U2t0WWNtcGxVRXN6TDJnMGNIa0taME00Y0Rkdk5FRkJRVWRvVjJReFdsRlJRVUZDUVUxQlVucENSa0ZwUVVoNWNFbFVaMlEyUTB3clFYcExVa2xwZVZoYVlrNDRVa3BSWjJkTVNXaDZjUXBUVHpSRFZsWTVlR0ozU1doQlVIUmlTRE12WlRScmRXUnBNSFpqYkZCTWRUSnNkVGhpU21sMFZ6aHVWMlJvTUdoTFNYVlhlRnBsTUUxQmIwZERRM0ZIQ2xOTk5EbENRVTFFUVRKalFVMUhVVU5OUm5NcmRXNUdNVlI1Ums5dldFbGpRblpUYzJ0d1dWSkhPR1UwUTJ4a1NrUTBSM1F4V1d4V1R5OXpjM1pIZVdrS1JFcEdOWFZTUkhKUGVFcERURmcyVFN0UlNYZE1ZVVZaZUZKcU1tNUpOMk5oWm14Vk1sUTRjMHhCYlVKeFdtaGFUV3g0UTJ4bVNYRnllVEozTVM4dk1ncFNPVk54Y1V0T2MxRkhlUzgxT1RSd2NrcFBSQW90TFMwdExVVk9SQ0JEUlZKVVNVWkpRMEZVUlMwdExTMHRDZz09In19fX0="}], "timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyzADAgEAMIICwgYJKoZIhvcNAQcCoIICszCCAq8CAQMxDTALBglghkgBZQMEAgEwgbgGCyqGSIb3DQEJEAEEoIGoBIGlMIGiAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgvs31/7DRRm4Abken+kCChhxSnCcdrFfS+RhRBNwyTe4CFQD29NJRSvRnC2TNE2dAR1RU1ya64RgPMjAyNjEwMjAxNTEwNDFaMAMCAQGgMqQwMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhoAAxggHcMIIB2AIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MTAyMDE1MTA0MVowLwYJKoZIhvcNAQkEMSIEIKLJxH8rfpuw1xi5MT7pRVIDUGbqpHyi2bDmoevTMIOqMIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCCF+Se8B6tiysO0Q1bBDvyBssaIP9p6uebYcNnROs0FtzBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQ6E1QvDJBh7rzBQy/Lio6LKiOLDDAKBggqhkjOPQQDAgRoMGYCMQDxhU45xIFeO/VwOLA1gA4oONgxXs+6y9+N+ogLV+cf69Tn8knNkEyRO+4X3UcscEICMQCCpEa6UXRjq0I/+2CFCZLXTSzLGuhSoMDkvHFWZtcbqYrF8xw7RaDqK7xcJ4cxpLE="}]}}, "messageSignature":{"messageDigest":{"algorithm":"SHA2_256", "digest":"CZSmNABjdR8kTo0saSFz0z9PCTKpWIXS3A9/mmBVJlA="}, "signature":"MEQCIHxoYG1zIOrWV+Zi/Iv4gWOzqZlTWwVSoqUj3IlpxDrwAiB78VQK44k3eABUH1G6Y+U8PstMMqkz+Y42QEt3MREzKQ=="}}
build/torch-xpu/moe.py CHANGED
@@ -58,8 +58,9 @@ from .compat import (
58
  )
59
  from .formats import get_supported_act_fns, is_mx, is_mxfp4, is_per_expert_global, mx_scale_family, normalize_global_scale, ue8m0_as_uint8, weight_format
60
  from .norm import norm_column_factor, rms_inv_rows, rms_norm_rows
 
61
  from .quant import _launch_act_quant, MX_ACT_QUANT, mx_act_quant_routed_scales
62
- from .scheduling import compute_grouped_scheduling, is_off_rank, off_rank
63
  from .epilogue import fused_glu
64
 
65
 
@@ -245,6 +246,23 @@ def _torch_weighted_reduce(down_out, top_k_index, top_k_weights, num_experts):
245
  return contrib.view(num_tokens, num_top_k, down_out.size(1)).sum(dim=1)
246
 
247
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
  def _host_glu(gate_up_out, act_fn, swiglu_alpha, swiglu_limit, gate):
249
  """The activation on the host, for the arms the epilogue does not fuse: a callable takes the
250
  raw GEMM output (interleaved gate|up columns when ``gate``) and returns the intermediate —
@@ -345,6 +363,10 @@ def moe_fused_grouped(
345
  down_proj: torch.Tensor, # (E, H, I)
346
  gate_up_proj_scale_inv: torch.Tensor,
347
  down_proj_scale_inv: torch.Tensor,
 
 
 
 
348
  gate_up_proj_weight_global_scale: torch.Tensor | None = None,
349
  down_proj_weight_global_scale: torch.Tensor | None = None,
350
  gate_up_proj_input_global_scale: torch.Tensor | None = None,
@@ -379,17 +401,24 @@ def moe_fused_grouped(
379
  ``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any
380
  callable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated
381
  projection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)
382
- — the swizzled layout is for the dot_scaled arm; weight-only chains take affine."""
383
- fmt = _block_format(
384
- gate_up_proj, gate_up_proj_scale_inv, down_proj, down_proj_scale_inv, activation_format
385
- )
386
  num_top_k = top_k_index.size(-1)
387
- glu = _fused_glu(act_fn, swiglu_alpha, swiglu_limit, simulate_unfused, gate)
388
- fused = glu["act_fn"] is not None
389
  NUM_EXPERTS = gate_up_proj.size(0)
390
  expert_start, gather_idx, scatter_idx = compute_grouped_scheduling(
391
  top_k_index, NUM_EXPERTS, num_top_k
392
  )
 
 
 
 
 
 
 
 
 
393
 
394
  # Phase 1: gate_up + SiLU + requant in the block format -> expert-ordered quantized
395
  # intermediate. scatter_idx=None: the down reads the intermediate in place. (C, Cs) under a
@@ -462,6 +491,10 @@ def moe_fused_batched(
462
  down_proj: torch.Tensor, # (E, H, I)
463
  gate_up_proj_scale_inv: torch.Tensor,
464
  down_proj_scale_inv: torch.Tensor,
 
 
 
 
465
  gate_up_proj_weight_global_scale: torch.Tensor | None = None,
466
  down_proj_weight_global_scale: torch.Tensor | None = None,
467
  gate_up_proj_input_global_scale: torch.Tensor | None = None,
@@ -498,14 +531,23 @@ def moe_fused_batched(
498
  ``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any
499
  callable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated
500
  projection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)
501
- — the swizzled layout is for the dot_scaled arm; weight-only chains take affine."""
 
 
 
 
 
 
 
 
 
 
 
502
  fmt = _block_format(
503
  gate_up_proj, gate_up_proj_scale_inv, down_proj, down_proj_scale_inv, activation_format
504
  )
505
  glu = _fused_glu(act_fn, swiglu_alpha, swiglu_limit, simulate_unfused, gate)
506
  fused = glu["act_fn"] is not None
507
- NUM_EXPERTS = gate_up_proj.size(0)
508
- expert_ids = top_k_index.reshape(-1)
509
  gather_idx = _gather_idx(top_k_index)
510
 
511
  # Phase 1: gate_up + SiLU + requant in the block format -> per-row quantized
@@ -587,6 +629,10 @@ def moe_unfused_grouped(
587
  down_proj: torch.Tensor,
588
  gate_up_proj_scale_inv: torch.Tensor,
589
  down_proj_scale_inv: torch.Tensor,
 
 
 
 
590
  gate_up_proj_weight_global_scale: torch.Tensor | None = None,
591
  down_proj_weight_global_scale: torch.Tensor | None = None,
592
  gate_up_proj_input_global_scale: torch.Tensor | None = None,
@@ -617,16 +663,22 @@ def moe_unfused_grouped(
617
  ``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any
618
  callable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated
619
  projection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)
620
- — the swizzled layout is for the dot_scaled arm; weight-only chains take affine."""
621
- fmt = _block_format(
622
- gate_up_proj, gate_up_proj_scale_inv, down_proj, down_proj_scale_inv, activation_format
623
- )
624
-
625
  num_top_k = top_k_index.size(-1)
626
  NUM_EXPERTS = gate_up_proj.size(0)
627
  expert_start, gather_idx, scatter_idx = compute_grouped_scheduling(
628
  top_k_index, NUM_EXPERTS, num_top_k
629
  )
 
 
 
 
 
 
 
630
 
631
  # gate_up as a plain GEMM (no gate epilogue) over gathered hidden -> expert-ordered (S, 2I).
632
  gate_up_in, gate_up_in_scale = _gate_up_activations(
@@ -866,6 +918,10 @@ def moe_unfused_batched(
866
  down_proj: torch.Tensor,
867
  gate_up_proj_scale_inv: torch.Tensor,
868
  down_proj_scale_inv: torch.Tensor,
 
 
 
 
869
  gate_up_proj_weight_global_scale: torch.Tensor | None = None,
870
  down_proj_weight_global_scale: torch.Tensor | None = None,
871
  gate_up_proj_input_global_scale: torch.Tensor | None = None,
@@ -895,12 +951,21 @@ def moe_unfused_batched(
895
  ``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any
896
  callable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated
897
  projection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)
898
- — the swizzled layout is for the dot_scaled arm; weight-only chains take affine."""
 
 
 
 
 
 
 
 
 
 
 
899
  fmt = _block_format(
900
  gate_up_proj, gate_up_proj_scale_inv, down_proj, down_proj_scale_inv, activation_format
901
  )
902
- NUM_EXPERTS = gate_up_proj.size(0)
903
- expert_ids = top_k_index.reshape(-1)
904
  gather_idx = _gather_idx(top_k_index)
905
 
906
  # gate_up as a plain GEMM (no gate epilogue) over gathered hidden -> (S, 2I).
 
58
  )
59
  from .formats import get_supported_act_fns, is_mx, is_mxfp4, is_per_expert_global, mx_scale_family, normalize_global_scale, ue8m0_as_uint8, weight_format
60
  from .norm import norm_column_factor, rms_inv_rows, rms_norm_rows
61
+ from .loading.scales import csf_weight_scales
62
  from .quant import _launch_act_quant, MX_ACT_QUANT, mx_act_quant_routed_scales
63
+ from .scheduling import compute_grouped_scheduling, is_off_rank, off_rank, routed_expert_start
64
  from .epilogue import fused_glu
65
 
66
 
 
246
  return contrib.view(num_tokens, num_top_k, down_out.size(1)).sum(dim=1)
247
 
248
 
249
+ def _csf_weight_scales(
250
+ gate_up_proj_scale_inv, gate_up_proj_scale_exceptions, gate_up_proj_scale_exception_offsets,
251
+ down_proj_scale_inv, down_proj_scale_exceptions, down_proj_scale_exception_offsets, expert_start,
252
+ ):
253
+ """Both projections' weight scales for the GEMMs: a CSF fixed stream (given its exceptions)
254
+ decodes, only the experts with routed rows in ``expert_start``; dense scales pass through."""
255
+ return (
256
+ csf_weight_scales(
257
+ gate_up_proj_scale_inv, gate_up_proj_scale_exceptions, gate_up_proj_scale_exception_offsets,
258
+ expert_start,
259
+ ),
260
+ csf_weight_scales(
261
+ down_proj_scale_inv, down_proj_scale_exceptions, down_proj_scale_exception_offsets, expert_start
262
+ ),
263
+ )
264
+
265
+
266
  def _host_glu(gate_up_out, act_fn, swiglu_alpha, swiglu_limit, gate):
267
  """The activation on the host, for the arms the epilogue does not fuse: a callable takes the
268
  raw GEMM output (interleaved gate|up columns when ``gate``) and returns the intermediate —
 
363
  down_proj: torch.Tensor, # (E, H, I)
364
  gate_up_proj_scale_inv: torch.Tensor,
365
  down_proj_scale_inv: torch.Tensor,
366
+ gate_up_proj_scale_exceptions: torch.Tensor | None = None,
367
+ gate_up_proj_scale_exception_offsets: torch.Tensor | None = None,
368
+ down_proj_scale_exceptions: torch.Tensor | None = None,
369
+ down_proj_scale_exception_offsets: torch.Tensor | None = None,
370
  gate_up_proj_weight_global_scale: torch.Tensor | None = None,
371
  down_proj_weight_global_scale: torch.Tensor | None = None,
372
  gate_up_proj_input_global_scale: torch.Tensor | None = None,
 
401
  ``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any
402
  callable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated
403
  projection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)
404
+ — the swizzled layout is for the dot_scaled arm; weight-only chains take affine.
405
+ ``*_proj_scale_exceptions``/``*_proj_scale_exception_offsets`` mark that projection's
406
+ ``*_proj_scale_inv`` as a CSF-compressed NVFP4 fixed stream (``prepare_nvfp4_csf_scales``);
407
+ the block decodes it, only the routed experts, before its GEMMs."""
408
  num_top_k = top_k_index.size(-1)
 
 
409
  NUM_EXPERTS = gate_up_proj.size(0)
410
  expert_start, gather_idx, scatter_idx = compute_grouped_scheduling(
411
  top_k_index, NUM_EXPERTS, num_top_k
412
  )
413
+ gate_up_proj_scale_inv, down_proj_scale_inv = _csf_weight_scales(
414
+ gate_up_proj_scale_inv, gate_up_proj_scale_exceptions, gate_up_proj_scale_exception_offsets,
415
+ down_proj_scale_inv, down_proj_scale_exceptions, down_proj_scale_exception_offsets, expert_start,
416
+ )
417
+ fmt = _block_format(
418
+ gate_up_proj, gate_up_proj_scale_inv, down_proj, down_proj_scale_inv, activation_format
419
+ )
420
+ glu = _fused_glu(act_fn, swiglu_alpha, swiglu_limit, simulate_unfused, gate)
421
+ fused = glu["act_fn"] is not None
422
 
423
  # Phase 1: gate_up + SiLU + requant in the block format -> expert-ordered quantized
424
  # intermediate. scatter_idx=None: the down reads the intermediate in place. (C, Cs) under a
 
491
  down_proj: torch.Tensor, # (E, H, I)
492
  gate_up_proj_scale_inv: torch.Tensor,
493
  down_proj_scale_inv: torch.Tensor,
494
+ gate_up_proj_scale_exceptions: torch.Tensor | None = None,
495
+ gate_up_proj_scale_exception_offsets: torch.Tensor | None = None,
496
+ down_proj_scale_exceptions: torch.Tensor | None = None,
497
+ down_proj_scale_exception_offsets: torch.Tensor | None = None,
498
  gate_up_proj_weight_global_scale: torch.Tensor | None = None,
499
  down_proj_weight_global_scale: torch.Tensor | None = None,
500
  gate_up_proj_input_global_scale: torch.Tensor | None = None,
 
531
  ``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any
532
  callable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated
533
  projection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)
534
+ — the swizzled layout is for the dot_scaled arm; weight-only chains take affine.
535
+ ``*_proj_scale_exceptions``/``*_proj_scale_exception_offsets`` mark that projection's
536
+ ``*_proj_scale_inv`` as a CSF-compressed NVFP4 fixed stream (``prepare_nvfp4_csf_scales``);
537
+ the block decodes it, only the routed experts, before its GEMMs."""
538
+ NUM_EXPERTS = gate_up_proj.size(0)
539
+ expert_ids = top_k_index.reshape(-1)
540
+ if gate_up_proj_scale_exceptions is not None or down_proj_scale_exceptions is not None:
541
+ gate_up_proj_scale_inv, down_proj_scale_inv = _csf_weight_scales(
542
+ gate_up_proj_scale_inv, gate_up_proj_scale_exceptions, gate_up_proj_scale_exception_offsets,
543
+ down_proj_scale_inv, down_proj_scale_exceptions, down_proj_scale_exception_offsets,
544
+ routed_expert_start(expert_ids, NUM_EXPERTS), # decode only the routed experts
545
+ )
546
  fmt = _block_format(
547
  gate_up_proj, gate_up_proj_scale_inv, down_proj, down_proj_scale_inv, activation_format
548
  )
549
  glu = _fused_glu(act_fn, swiglu_alpha, swiglu_limit, simulate_unfused, gate)
550
  fused = glu["act_fn"] is not None
 
 
551
  gather_idx = _gather_idx(top_k_index)
552
 
553
  # Phase 1: gate_up + SiLU + requant in the block format -> per-row quantized
 
629
  down_proj: torch.Tensor,
630
  gate_up_proj_scale_inv: torch.Tensor,
631
  down_proj_scale_inv: torch.Tensor,
632
+ gate_up_proj_scale_exceptions: torch.Tensor | None = None,
633
+ gate_up_proj_scale_exception_offsets: torch.Tensor | None = None,
634
+ down_proj_scale_exceptions: torch.Tensor | None = None,
635
+ down_proj_scale_exception_offsets: torch.Tensor | None = None,
636
  gate_up_proj_weight_global_scale: torch.Tensor | None = None,
637
  down_proj_weight_global_scale: torch.Tensor | None = None,
638
  gate_up_proj_input_global_scale: torch.Tensor | None = None,
 
663
  ``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any
664
  callable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated
665
  projection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)
666
+ — the swizzled layout is for the dot_scaled arm; weight-only chains take affine.
667
+ ``*_proj_scale_exceptions``/``*_proj_scale_exception_offsets`` mark that projection's
668
+ ``*_proj_scale_inv`` as a CSF-compressed NVFP4 fixed stream (``prepare_nvfp4_csf_scales``);
669
+ the block decodes it, only the routed experts, before its GEMMs."""
 
670
  num_top_k = top_k_index.size(-1)
671
  NUM_EXPERTS = gate_up_proj.size(0)
672
  expert_start, gather_idx, scatter_idx = compute_grouped_scheduling(
673
  top_k_index, NUM_EXPERTS, num_top_k
674
  )
675
+ gate_up_proj_scale_inv, down_proj_scale_inv = _csf_weight_scales(
676
+ gate_up_proj_scale_inv, gate_up_proj_scale_exceptions, gate_up_proj_scale_exception_offsets,
677
+ down_proj_scale_inv, down_proj_scale_exceptions, down_proj_scale_exception_offsets, expert_start,
678
+ )
679
+ fmt = _block_format(
680
+ gate_up_proj, gate_up_proj_scale_inv, down_proj, down_proj_scale_inv, activation_format
681
+ )
682
 
683
  # gate_up as a plain GEMM (no gate epilogue) over gathered hidden -> expert-ordered (S, 2I).
684
  gate_up_in, gate_up_in_scale = _gate_up_activations(
 
918
  down_proj: torch.Tensor,
919
  gate_up_proj_scale_inv: torch.Tensor,
920
  down_proj_scale_inv: torch.Tensor,
921
+ gate_up_proj_scale_exceptions: torch.Tensor | None = None,
922
+ gate_up_proj_scale_exception_offsets: torch.Tensor | None = None,
923
+ down_proj_scale_exceptions: torch.Tensor | None = None,
924
+ down_proj_scale_exception_offsets: torch.Tensor | None = None,
925
  gate_up_proj_weight_global_scale: torch.Tensor | None = None,
926
  down_proj_weight_global_scale: torch.Tensor | None = None,
927
  gate_up_proj_input_global_scale: torch.Tensor | None = None,
 
951
  ``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any
952
  callable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated
953
  projection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)
954
+ — the swizzled layout is for the dot_scaled arm; weight-only chains take affine.
955
+ ``*_proj_scale_exceptions``/``*_proj_scale_exception_offsets`` mark that projection's
956
+ ``*_proj_scale_inv`` as a CSF-compressed NVFP4 fixed stream (``prepare_nvfp4_csf_scales``);
957
+ the block decodes it, only the routed experts, before its GEMMs."""
958
+ NUM_EXPERTS = gate_up_proj.size(0)
959
+ expert_ids = top_k_index.reshape(-1)
960
+ if gate_up_proj_scale_exceptions is not None or down_proj_scale_exceptions is not None:
961
+ gate_up_proj_scale_inv, down_proj_scale_inv = _csf_weight_scales(
962
+ gate_up_proj_scale_inv, gate_up_proj_scale_exceptions, gate_up_proj_scale_exception_offsets,
963
+ down_proj_scale_inv, down_proj_scale_exceptions, down_proj_scale_exception_offsets,
964
+ routed_expert_start(expert_ids, NUM_EXPERTS), # decode only the routed experts
965
+ )
966
  fmt = _block_format(
967
  gate_up_proj, gate_up_proj_scale_inv, down_proj, down_proj_scale_inv, activation_format
968
  )
 
 
969
  gather_idx = _gather_idx(top_k_index)
970
 
971
  # gate_up as a plain GEMM (no gate epilogue) over gathered hidden -> (S, 2I).
build/torch-xpu/scheduling.py CHANGED
@@ -86,13 +86,15 @@ def _exclusive_offsets_kernel(
86
  ExpertFreq, ExpertStart, Counters, NUM_EXPERTS: tl.constexpr
87
  ):
88
  """Exclusive cumsum of per-expert token counts → ``expert_start`` (leading 0, trailing the
89
- local count), and zero the scatter counters, the EP-sentinel bucket's included — one launch."""
 
90
  offs = tl.arange(0, NUM_EXPERTS)
91
  incl = tl.cumsum(tl.load(ExpertFreq + offs), 0)
92
  tl.store(ExpertStart, 0)
93
  tl.store(ExpertStart + 1 + offs, incl)
94
- tl.store(Counters + offs, tl.zeros([NUM_EXPERTS], tl.int32))
95
- tl.store(Counters + NUM_EXPERTS, 0)
 
96
 
97
 
98
  @triton.jit
@@ -179,20 +181,25 @@ def compute_grouped_scheduling(
179
  return expert_start, gather_idx, scatter_idx
180
 
181
 
182
- @compile_time_only_triton_op(
183
- add_op_namespace_prefix("compute_grouped_scheduling"), mutates_args=(), opaque=True
184
- )
185
- def _compute_grouped_scheduling(
186
- expert_ids: torch.Tensor, num_experts: int, num_top_k: int
187
- ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
 
 
 
 
 
 
 
 
 
188
  device = expert_ids.device
189
- expert_ids = expert_ids.int().contiguous() # routing kernels index with unit stride
190
  num_routed_tokens = expert_ids.numel() # S = num_tokens * num_top_k
191
  expert_freq = torch.zeros(num_experts, dtype=torch.int32, device=device)
192
  expert_start = torch.empty(num_experts + 1, dtype=torch.int32, device=device)
193
- counters = torch.empty(num_experts + 1, dtype=torch.int32, device=device)
194
- perm = torch.empty(num_routed_tokens, dtype=torch.int32, device=device)
195
- perm_token = torch.empty(num_routed_tokens, dtype=torch.int32, device=device)
196
  with device_context(device):
197
  compile_time_only_triton_wrap(_count_kernel)[
198
  (triton.cdiv(num_routed_tokens, _ROUTING_BLOCK_SIZE),)
@@ -209,6 +216,30 @@ def _compute_grouped_scheduling(
209
  counters,
210
  NUM_EXPERTS=num_experts,
211
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  compile_time_only_triton_wrap(_scatter_kernel)[
213
  (triton.cdiv(num_routed_tokens, _ROUTING_BLOCK_SIZE),)
214
  ](
 
86
  ExpertFreq, ExpertStart, Counters, NUM_EXPERTS: tl.constexpr
87
  ):
88
  """Exclusive cumsum of per-expert token counts → ``expert_start`` (leading 0, trailing the
89
+ local count), and zero the scatter counters, the EP-sentinel bucket's included — one launch.
90
+ ``Counters`` None (no scatter follows) skips them."""
91
  offs = tl.arange(0, NUM_EXPERTS)
92
  incl = tl.cumsum(tl.load(ExpertFreq + offs), 0)
93
  tl.store(ExpertStart, 0)
94
  tl.store(ExpertStart + 1 + offs, incl)
95
+ if Counters is not None:
96
+ tl.store(Counters + offs, tl.zeros([NUM_EXPERTS], tl.int32))
97
+ tl.store(Counters + NUM_EXPERTS, 0)
98
 
99
 
100
  @triton.jit
 
181
  return expert_start, gather_idx, scatter_idx
182
 
183
 
184
+ def routed_expert_start(expert_ids: torch.Tensor, num_experts: int) -> torch.Tensor | None:
185
+ """``expert_start`` of an unsorted (batched) routing: its consumers only need which experts
186
+ have routed rows, to skip per-expert work on the rest, so only the count and offset launches
187
+ run (no sort). ``None`` (every expert) when the expert count is not a power of 2, which the
188
+ scheduling kernels cannot hold."""
189
+ if num_experts & (num_experts - 1):
190
+ return None
191
+ return _compute_expert_start(expert_ids, num_experts)
192
+
193
+
194
+ def _launch_expert_start(
195
+ expert_ids: torch.Tensor, num_experts: int, counters: torch.Tensor | None = None
196
+ ) -> torch.Tensor:
197
+ """The count + exclusive-offset launches → ``expert_start``; ``counters`` (the scatter's
198
+ per-expert cursors, when a sort follows) is zeroed in the same launch."""
199
  device = expert_ids.device
 
200
  num_routed_tokens = expert_ids.numel() # S = num_tokens * num_top_k
201
  expert_freq = torch.zeros(num_experts, dtype=torch.int32, device=device)
202
  expert_start = torch.empty(num_experts + 1, dtype=torch.int32, device=device)
 
 
 
203
  with device_context(device):
204
  compile_time_only_triton_wrap(_count_kernel)[
205
  (triton.cdiv(num_routed_tokens, _ROUTING_BLOCK_SIZE),)
 
216
  counters,
217
  NUM_EXPERTS=num_experts,
218
  )
219
+ return expert_start
220
+
221
+
222
+ @compile_time_only_triton_op(
223
+ add_op_namespace_prefix("compute_expert_start"), mutates_args=(), opaque=True
224
+ )
225
+ def _compute_expert_start(expert_ids: torch.Tensor, num_experts: int) -> torch.Tensor:
226
+ return _launch_expert_start(expert_ids.int().contiguous(), num_experts)
227
+
228
+
229
+ @compile_time_only_triton_op(
230
+ add_op_namespace_prefix("compute_grouped_scheduling"), mutates_args=(), opaque=True
231
+ )
232
+ def _compute_grouped_scheduling(
233
+ expert_ids: torch.Tensor, num_experts: int, num_top_k: int
234
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
235
+ device = expert_ids.device
236
+ expert_ids = expert_ids.int().contiguous() # routing kernels index with unit stride
237
+ num_routed_tokens = expert_ids.numel() # S = num_tokens * num_top_k
238
+ counters = torch.empty(num_experts + 1, dtype=torch.int32, device=device)
239
+ expert_start = _launch_expert_start(expert_ids, num_experts, counters)
240
+ perm = torch.empty(num_routed_tokens, dtype=torch.int32, device=device)
241
+ perm_token = torch.empty(num_routed_tokens, dtype=torch.int32, device=device)
242
+ with device_context(device):
243
  compile_time_only_triton_wrap(_scatter_kernel)[
244
  (triton.cdiv(num_routed_tokens, _ROUTING_BLOCK_SIZE),)
245
  ](
build/torch-xpu/symbols.json CHANGED
@@ -1,13 +1,13 @@
1
  {
2
  "schema_version": 1,
3
- "module": "_finegrained_kernels_xpu_78a2a29",
4
  "functions": [
5
  {
6
  "name": "matmul_2d",
7
  "qualname": "matmul_2d",
8
- "module": "_finegrained_kernels_xpu_78a2a29.matmul",
9
  "kind": "function",
10
- "doc": "Dense (2D) quantized matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4) — the single-GEMM sibling of\n``matmul_grouped``/``matmul_batched``, taking the same ``As``/``Bs`` scale spec,\n``activation_format`` / gate|up fusion kwargs, and inferred quant block (no ``block_size`` argument — it\nfalls out of the weight-scale shape, so the data can't disagree with a parameter).\n\n``As`` is the activation block-scale spec, same as the routed ops: ``None`` → the op quantizes raw\n``A`` dynamically; a per-tensor scalar → static (calibrated) FP8 activation scale; block scales →\npre-quantized ``A``. ``Bs`` is the weight block scale. ``a_global_scale``/``b_global_scale`` are the\ntwo-level NVFP4 per-tensor second-level scales (calibrated ``input_scale`` ``g_a`` and\n``weight_scale_2`` ``g_b``) — provided, never computed; the op folds ``g_a·g_b`` onto the\naccumulator (``a_global_scale`` rides raw ``A`` or a pre-quantized ``As`` alike).\n``output_global_scale`` (NVFP4 requant only) is the NEXT proj's provided ``input_scale``:\nthe fused requant normalizes the GLU intermediate by it, returning ``(C, Cs)`` the down-proj\nconsumes as ``As=Cs, a_global_scale=output_global_scale``.\n\n``activation_format`` is the activations' quantization: ``None`` (default) = the weights' own\nformat, ``\"bf16\"`` = weight-only (no activation quant), or an explicit ``\"fp8\"`` / ``\"mxfp8\"`` /\n``\"mxfp4\"`` / ``\"nvfp4\"`` (``\"mxfp8\"`` on MXFP4 weights = the W4A8 chain; ``check_activation_format``\nhas the per-family matrix). ``gate=True`` reads ``B`` as the interleaved ``(2N, K)`` gate|up weight and\nfuses the ``act_fn`` GLU (``swiglu_alpha``/``swiglu_limit`` its clamped variant), returning the\n``[..., N]`` intermediate (``act_fn=None``: the raw ``[..., 2N]`` gate|up output instead); ``quantize_output=True`` (MX weights only) stores that intermediate in\n``activation_format`` and returns ``(C, Cs)`` for the next op.\n\nRoutes by weight dtype + inferred block: ``Bs`` None → full-precision; MX/NVFP4 (int8/E4M3 weights\nwith UE8M0 group-32 or E4M3 group-16 ``Bs``) → ``mx_dynamic_matmul``; tensor-wide FP8 (scalar\n``Bs``) → ``w8a8_tensor_dynamic_fp8_matmul``; block FP8 → the static variant when ``As`` is a\nper-tensor scalar, else dynamic.",
11
  "signature": {
12
  "parameters": [
13
  {
@@ -100,6 +100,18 @@
100
  "default": "None",
101
  "annotation": "torch.Tensor | None"
102
  },
 
 
 
 
 
 
 
 
 
 
 
 
103
  {
104
  "name": "output_global_scale",
105
  "kind": "KEYWORD_ONLY",
@@ -113,9 +125,9 @@
113
  {
114
  "name": "matmul_batched",
115
  "qualname": "matmul_batched",
116
- "module": "_finegrained_kernels_xpu_78a2a29.batched",
117
  "kind": "function",
118
- "doc": "Batched matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4, or full-precision). Routes one\nprogram per routed row (``expert_ids`` gives its expert).\n\n``As`` marks ``A`` as already quantized (framework-precomputed scales, or a requantized\nintermediate handed to the down projection); a per-tensor scalar ``As`` is instead the static\n(calibrated) activation scale for block-scale FP8 weights — the op quantizes raw ``A`` against\nit; ``None`` = raw ``A``, quantized dynamically by the op in ``activation_format`` (``None`` =\nthe weights' own format — fp8/E4M3 offline for bd/tensor, inline for MX; ``\"bf16\"`` = weight-only;\n``\"mxfp4\"`` = packed E2M1 activations). ``Bs`` ``None`` = unquantized BF16/FP16 weights.\n``quantize_output`` requantizes the output into ``activation_format`` — the return is then\n``(C, Cs)``. ``gate``/``act_fn``/``swiglu_alpha``/``swiglu_limit`` fuse the gate|up GLU into the\nepilogue; ``act_fn=None`` with ``gate`` skips it, returning the raw interleaved gate|up\noutput for a host-side activation.\n``As``/``Bs`` are each a bare block-scale tensor; the two-level NVFP4\nsecond-level scales ride the separate ``a_global_scale``/``b_global_scale`` (fp32 per-tensor,\nweights per-expert ``(E,)``; from ``nvfp4_quantize_two_level``), and the op folds ``g_a · g_b``\nonto the accumulator. The activation global ``g_a`` is CALIBRATED (the checkpoint's\n``input_scale``): ``a_global_scale=g_a`` with a raw ``A`` has the op quantize ``A / g_a`` per\nblock, and rides a pre-quantized ``As`` the same way. Under an NVFP4 requant the\nfused requant normalizes the GLU intermediate by the PROVIDED ``output_global_scale`` (the next\nproj's calibrated ``input_scale``) before the block quant and returns ``[C, Cs]``; the down\nconsumes it as ``As=Cs, a_global_scale=output_global_scale``. ``gather_idx``/``scatter_idx`` (each None or a ``(S,)`` map)\naddress the source row of ``A`` / destination row of ``C`` per program — None means row\n``s``; the gather lets the gate_up read unexpanded activations (source row\n``s // num_top_k``) with no copy.\n\nRoutes by what the weight tensors themselves say (there is no ``block_size``\nparameter — the quantization block is derived from the scale shape,\n``weight_block_size``):\n- ``Bs`` None → ``full_precision_matmul_batched`` (plain dot, no scales anywhere).\n- MX weights — ``int8`` (packed E2M1) or ``float8_e4m3fn`` (E4M3) with UE8M0\n group-32 ``Bs`` → ``mx_dynamic_matmul_batched``.\n- one scale per expert (``Bs`` ``(E,)``/``(E, 1, 1)``) →\n ``w8a8_tensor_dynamic_fp8_matmul_batched``.\n- block scales (``Bs`` ``(E, N/bn, K/bk)``) → ``w8a8_block_dynamic_fp8_matmul_batched``.",
119
  "signature": {
120
  "parameters": [
121
  {
@@ -226,6 +238,18 @@
226
  "default": "None",
227
  "annotation": "torch.Tensor | None"
228
  },
 
 
 
 
 
 
 
 
 
 
 
 
229
  {
230
  "name": "output_global_scale",
231
  "kind": "KEYWORD_ONLY",
@@ -239,9 +263,9 @@
239
  {
240
  "name": "matmul_grouped",
241
  "qualname": "matmul_grouped",
242
- "module": "_finegrained_kernels_xpu_78a2a29.grouped",
243
  "kind": "function",
244
- "doc": "Grouped matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4, or full-precision).\n``expert_start`` is the ``(E+1,)`` tiling schedule from one ``compute_grouped_scheduling``\npass, shared by every grouped GEMM of the layer (the expert sort is virtual — nothing is\nphysically permuted).\n\n``As`` marks ``A`` as already quantized (framework-precomputed scales, or a requantized\nintermediate handed to the down projection); a per-tensor scalar ``As`` is instead the static\n(calibrated) activation scale for block-scale FP8 weights — the op quantizes raw ``A`` against\nit; ``None`` = raw ``A``, quantized dynamically by the op in ``activation_format`` (``None`` =\nthe weights' own format — fp8/E4M3, or the fp4 chains; ``\"bf16\"`` = weight-only; ``\"mxfp4\"`` =\npacked E2M1 activations). ``Bs`` ``None`` = unquantized BF16/FP16 weights.\n``quantize_output`` requantizes the output into ``activation_format`` — the return is then\n``(C, Cs)``. ``gate``/``act_fn``/``swiglu_alpha``/``swiglu_limit`` fuse the gate|up GLU into the\nepilogue; ``act_fn=None`` with ``gate`` skips it, returning the raw interleaved gate|up\noutput for a host-side activation.\n``As``/``Bs`` are each a bare block-scale tensor; the two-level NVFP4 second-level scales ride\nthe separate ``a_global_scale``/``b_global_scale`` (fp32 per-tensor, weights per-expert ``(E,)``;\nfrom ``nvfp4_quantize_two_level``), and the op folds ``g_a · g_b`` onto the accumulator. The\nactivation global ``g_a`` is CALIBRATED (the checkpoint's ``input_scale``): ``a_global_scale=g_a``\nwith a raw ``A`` has the op quantize ``A / g_a`` per block, and rides a pre-quantized ``As`` the\nsame way. Under an NVFP4 requant the fused requant normalizes the GLU intermediate by the\nPROVIDED ``output_global_scale`` (the next proj's calibrated ``input_scale``) before the block\nquant and returns ``[C, Cs]``; the down consumes it as ``As=Cs, a_global_scale=output_global_scale``.\nRow order is carried by the standalone maps: ``gather_idx`` gathers ``A`` (``None`` ->\nalready expert-ordered), ``scatter_idx`` scatters the output. The fused MoE chain is one\nscheduling pass: gate_up with ``scatter_idx=None`` + ``gate=True`` + ``quantize_output=True``,\nthen down with ``gather_idx=None`` and the\nintermediate's scales as ``As``. EP-sentinel routes sit past ``expert_start[-1]``, which\nno tile reaches.\n\nRoutes by what the weight tensors themselves say (there is no ``block_size``\nparameter — the quantization block is derived from the scale shape,\n``weight_block_size``):\n- ``Bs`` None → ``full_precision_matmul_grouped`` (plain dot, no scales anywhere).\n- MX weights — ``int8`` (packed E2M1) or ``float8_e4m3fn`` (E4M3) with UE8M0\n group-32 ``Bs`` ��� ``mx_dynamic_matmul_grouped``.\n- one scale per expert (``Bs`` ``(E,)``/``(E, 1, 1)``) →\n ``w8a8_tensor_dynamic_fp8_matmul_grouped``.\n- block scales (``Bs`` ``(E, N/bn, K/bk)``) → ``w8a8_block_dynamic_fp8_matmul_grouped``.",
245
  "signature": {
246
  "parameters": [
247
  {
@@ -352,6 +376,18 @@
352
  "default": "None",
353
  "annotation": "torch.Tensor | None"
354
  },
 
 
 
 
 
 
 
 
 
 
 
 
355
  {
356
  "name": "output_global_scale",
357
  "kind": "KEYWORD_ONLY",
@@ -365,9 +401,9 @@
365
  {
366
  "name": "moe_fused_batched",
367
  "qualname": "moe_fused_batched",
368
- "module": "_finegrained_kernels_xpu_78a2a29.moe",
369
  "kind": "function",
370
- "doc": "Fused batched MoE (decode): gate_up + SiLU + requant epilogue → per-row quantized\nintermediate → batched down → routing-weighted top-k reduce. Returns\n``(num_tokens, hidden_dim)``. The base ops dispatch on the weight dtypes / scale\nlayout (block-dynamic FP8, MXFP8/MXFP4, NVFP4 — decode runs the software/swap arms\nbelow the native mxf4nvf4 M=128 staging); ``activation_format`` names the activation\nquantization for the whole block — activations and the fused intermediate requant\ncarry it (``\"mxfp4\"`` runs the all-fp4 W4A4 chain, ``\"bf16\"`` is weight-only); ``None``\nfollows the weight format, and the ops validate the pairing. The\n``*_proj_input_global_scale`` pair is the NVFP4 activation second level (a checkpoint's\ncalibrated per-projection ``input_scale``): the gate_up quantizes hidden against its own,\nrequants the intermediate against the down's, and the down consumes that as its activation\nglobal. ``None`` is dynamic quant everywhere else. ``simulate_unfused`` (testing) rounds each\nstep through the activation dtype so the output matches the unfused reference to\nreduce order. ``act_fn`` is a\n``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any\ncallable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated\nprojection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)\n— the swizzled layout is for the dot_scaled arm; weight-only chains take affine.",
371
  "signature": {
372
  "parameters": [
373
  {
@@ -412,6 +448,30 @@
412
  "default": null,
413
  "annotation": "torch.Tensor"
414
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
415
  {
416
  "name": "gate_up_proj_weight_global_scale",
417
  "kind": "POSITIONAL_OR_KEYWORD",
@@ -521,9 +581,9 @@
521
  {
522
  "name": "moe_fused_grouped",
523
  "qualname": "moe_fused_grouped",
524
- "module": "_finegrained_kernels_xpu_78a2a29.moe",
525
  "kind": "function",
526
- "doc": "Fused grouped MoE (prefill): gather gate_up + SiLU + requant epilogue → quantized\nexpert-ordered intermediate → grouped down → routing-weighted top-k reduce. Returns\n``(num_tokens, hidden_dim)``. The base ops dispatch on the weight dtypes / scale\nlayout (block-dynamic FP8, MXFP8/MXFP4, NVFP4); ``activation_format`` names the activation\nquantization for the whole block — activations and the fused intermediate requant\ncarry it (``\"mxfp4\"``/``\"nvfp4\"`` run all-fp4 W4A4 chains, ``\"bf16\"`` is weight-only);\n``None`` follows the weight format, and the ops validate the pairing. The\n``*_proj_input_global_scale`` pair is the NVFP4 activation second level (a checkpoint's\ncalibrated per-projection ``input_scale``): the gate_up quantizes hidden against its own,\nrequants the intermediate against the down's, and the down consumes that as its activation\nglobal. ``None`` is dynamic quant everywhere else. ``simulate_unfused`` (testing) rounds each step through\nthe activation dtype so the output matches the unfused reference to reduce order. ``act_fn`` is a\n``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any\ncallable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated\nprojection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)\n— the swizzled layout is for the dot_scaled arm; weight-only chains take affine.",
527
  "signature": {
528
  "parameters": [
529
  {
@@ -568,6 +628,30 @@
568
  "default": null,
569
  "annotation": "torch.Tensor"
570
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
571
  {
572
  "name": "gate_up_proj_weight_global_scale",
573
  "kind": "POSITIONAL_OR_KEYWORD",
@@ -677,7 +761,7 @@
677
  {
678
  "name": "embedding_lookup",
679
  "qualname": "embedding_lookup",
680
- "module": "_finegrained_kernels_xpu_78a2a29.embedding",
681
  "kind": "function",
682
  "doc": "Gather and dequantize selected rows without expanding the embedding table.\n\n``weight_format`` selects ``fp8``, ``nvfp4``, ``mxfp8``, ``mxfp4``, ``int8``, or ``int4``.\nBy default, a global scale selects NVFP4, signed int8 weights select INT8, and otherwise\nFP8 is used. FP8 accepts scalar, per-row, or square block scales (``block_size``).\nNVFP4 uses E4M3 group-16 scales and one FP32 multiplier; MX formats use UE8M0 group-32\nscales. FP4 packs adjacent columns, low nibble first. INT8 uses per-row scales; INT4\npacks adjacent vocabulary rows and uses per-row column groups inferred from its scale\ngrid. Integer values are signed, symmetric, and have no zero point.\n\nOutputs default to the floating scale dtype, or bf16 for NVFP4/MX. Table/grid strides\nmay describe TP slices. Indices follow ``torch.nn.functional.embedding``: negative and\nout-of-range values fail; padding indices look up their stored row. Empty, repeated,\nand noncontiguous indices work.",
683
  "signature": {
@@ -731,7 +815,7 @@
731
  {
732
  "name": "get_supported_act_fns",
733
  "qualname": "get_supported_act_fns",
734
- "module": "_finegrained_kernels_xpu_78a2a29.formats",
735
  "kind": "function",
736
  "doc": "The activation names the gate|up epilogue fuses in-kernel; any other activation is applied\non the host by the MoE forwards (``act_fn`` as a callable).",
737
  "signature": {
@@ -742,7 +826,7 @@
742
  {
743
  "name": "get_supported_norms",
744
  "qualname": "get_supported_norms",
745
- "module": "_finegrained_kernels_xpu_78a2a29.norm",
746
  "kind": "function",
747
  "doc": "The norm names the kernels fuse (``post_expert_norm``), each ``x * factor * rsqrt(mean +\neps)`` over the row: ``\"rms_norm\"`` scales the normalized row by ``weight``,\n``\"centered_rms_norm\"`` by ``1 + weight`` (the zero-centered parameterization), and\n``\"input_scaled_rms_norm\"`` scales by ``1 + weight`` BEFORE normalizing, so the mean square\nis taken on the scaled row. Anything else stays a host callable.",
748
  "signature": {
@@ -753,7 +837,7 @@
753
  {
754
  "name": "rms_norm_rows",
755
  "qualname": "rms_norm_rows",
756
- "module": "_finegrained_kernels_xpu_78a2a29.norm",
757
  "kind": "function",
758
  "doc": "RMS-normalize ``(S, H)`` rows in one launch, in the ``get_supported_norms()`` form named by\n``norm`` (fp32 accumulate, input dtype out). The MoE chain folds this into\n``weighted_reduce`` instead; this is the standalone form.",
759
  "signature": {
@@ -789,7 +873,7 @@
789
  {
790
  "name": "swizzle_mx_scales",
791
  "qualname": "swizzle_mx_scales",
792
- "module": "_finegrained_kernels_xpu_78a2a29.swizzle",
793
  "kind": "function",
794
  "doc": "Reorder a block-scale tensor into the ``SWIZZLE_32_4_4`` layout the Blackwell tcgen05\nscaled-MMA consumes, one triton launch per matrix (``_swizzle_scales_kernel`` — no torch\npermute/transpose copies). The scale values are unchanged — this only rearranges them from\nplain row-major into the swizzled order the tensor core reads directly (the same layout\ncuBLAS/CUTLASS require for MXFP8/NVFP4 ``scaled_mm``). Plain row-major forces a gather that\ncaps the scaled dot below the fp8/fp4 peak; the swizzle removes it. Apply to weight scales\nonce at model load; the ops accept the result directly.\n\n``scale`` is the per-block scale grid — UE8M0 (``float8_e8m0fnu``, group-32 MXFP8/MXFP4) or\nE4M3 (``float8_e4m3fn``, group-16 NVFP4); the reorder is dtype-agnostic (moves bytes):\n\n- 2D ``(rows, K // group)``: one matrix (a dense weight's scale).\n- 3D ``(E, rows, K // group)``: an expert stack, each expert swizzled independently so its\n blocks stay ``ceil(rows/128)``-aligned (the reader indexes expert ``e`` at\n ``e * ceil(rows/128)``; byte-identical to a flat swizzle when ``rows % 128 == 0``).\n\n``gather_idx`` (2D only): a 1-D ``(padded_rows,)`` index mapping each output (sorted) row to\nits source row in ``scale`` (``-1`` = padding → zero row), folded into the kernel's load — the\nrouted/expert-sorted, per-tile-padded layout a grouped GEMM reads affine per BM=128 tile.\n``padded_rows`` must be a multiple of 128.\n\n``rows``/``cols`` are zero-padded to (128, 4) multiples; returns the 5D\n``(G, row_blocks, ceil(cols/4), 2, 256)`` artifact the ops read — ``G`` the expert count (1 for\na matrix), so an expert stack shards/gathers on its leading dim. Bit-identical to CUTLASS's\npacker (verified).",
795
  "signature": {
@@ -813,7 +897,7 @@
813
  {
814
  "name": "unswizzle_mx_scales",
815
  "qualname": "unswizzle_mx_scales",
816
- "module": "_finegrained_kernels_xpu_78a2a29.swizzle",
817
  "kind": "function",
818
  "doc": "Inverse of ``swizzle_mx_scales``: a SWIZZLE_32_4_4 artifact back to the plain row-major\n``(rows, cols)`` grid — or ``(num_experts, rows, cols)`` for an expert stack — with the\n(128, 4) padding trimmed. Pure reshape/permute on the byte view (no kernel); it runs at\nsave/dequantize time, never on a forward, so the torch-level cost is irrelevant.\n\n``rows``/``cols`` are the LOGICAL dims of ONE matrix (for a gate|up slab, the full ``2N``);\nboth are trimmed back out of the (128, 4) padding. ``num_experts`` selects the stacked\n``(E, rows, cols)`` result and must match the artifact's leading dim.",
819
  "signature": {
@@ -846,10 +930,76 @@
846
  "return_annotation": "torch.Tensor"
847
  }
848
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
849
  {
850
  "name": "mxfp8_act_quant",
851
  "qualname": "mxfp8_act_quant",
852
- "module": "_finegrained_kernels_xpu_78a2a29.quant",
853
  "kind": "function",
854
  "doc": "Quantize ``(T, K)`` activations to MX once (E4M3 values + UE8M0 group-32 uint8 scales)\ninstead of inline per weight-tile — the fused gate_up re-ran the inline quant per N-tile\n(16x redundant amax/convert ALU + 2x act bytes), which held it at ~380 TFLOPS while the\npre-quantized down kernel ran at ~1080. One pass costs ~50µs at 8k tokens. Bit-exact with\nthe inline form (same group boundaries). ``swizzled=True`` emits the scale directly in\nSWIZZLE_32_4_4 for the tcgen05 fast path (same dense grid, per-element store).",
855
  "signature": {
@@ -873,7 +1023,7 @@
873
  {
874
  "name": "mxfp4_act_quant",
875
  "qualname": "mxfp4_act_quant",
876
- "module": "_finegrained_kernels_xpu_78a2a29.quant",
877
  "kind": "function",
878
  "doc": "Quantize ``(T, K)`` activations to MXFP4 in one kernel pass: packed-E2M1 values\n(``(T, K//2)`` int8, two codes per byte, first value in the low nibble) + UE8M0\ngroup-32 uint8 scales (``(T, K//32)``, amax/6 ceil'd to a power of two). Bit-identical\nto the fused epilogues' inline form (shared ``mx_act_quant_inline`` arm). Feeds the\nW4A4 arm of the MX matmul ops; quantizing activations to fp4 at runtime is an\naccuracy call the caller owns — the ops never do it implicitly. ``swizzled=True`` emits the\nscale directly in SWIZZLE_32_4_4 for the tcgen05 fast path.",
879
  "signature": {
@@ -897,7 +1047,7 @@
897
  {
898
  "name": "nvfp4_act_quant",
899
  "qualname": "nvfp4_act_quant",
900
- "module": "_finegrained_kernels_xpu_78a2a29.quant",
901
  "kind": "function",
902
  "doc": "Quantize ``(T, K)`` activations to NVFP4 in one kernel pass: packed-E2M1 values\n(``(T, K//2)`` int8) + E4M3 group-16 block scales (``(T, K//16)`` — ``amax/6`` rounded to\nE4M3, NOT a power of two; values divide by the DECODED scale before the E2M1 grid,\nthe standard two-step). ``global_scale`` is the CALIBRATED per-tensor second level\n(fp32, the checkpoint's ``input_scale``): values are normalized by it before\nthe block quant, so block scales stay in e4m3 range regardless of the activation's\ndynamic range — the canonical two-level format. The GEMM folds ``g_a·g_b`` back onto\nthe accumulator (pass ``As=scales`` with ``a_global_scale=global_scale``). Per-expert globals\nneed each row's expert, which ``expert_index`` gives where the caller already holds that map\n(the batched op's ``expert_ids``, sentinels and all) — it is read only when the globals are\nper expert, and ``mx_act_quant_grouped`` needs none at all, its tiles carrying an expert.\n``None`` = single-level (``g_a = 1``). ``swizzled=True`` emits the scale directly in\nSWIZZLE_32_4_4 for the tcgen05 fast path.",
903
  "signature": {
 
1
  {
2
  "schema_version": 1,
3
+ "module": "_finegrained_kernels_xpu_bbd13a8",
4
  "functions": [
5
  {
6
  "name": "matmul_2d",
7
  "qualname": "matmul_2d",
8
+ "module": "_finegrained_kernels_xpu_bbd13a8.matmul",
9
  "kind": "function",
10
+ "doc": "Dense (2D) quantized matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4) — the single-GEMM sibling of\n``matmul_grouped``/``matmul_batched``, taking the same ``As``/``Bs`` scale spec,\n``activation_format`` / gate|up fusion kwargs, and inferred quant block (no ``block_size`` argument — it\nfalls out of the weight-scale shape, so the data can't disagree with a parameter).\n\n``As`` is the activation block-scale spec, same as the routed ops: ``None`` → the op quantizes raw\n``A`` dynamically; a per-tensor scalar → static (calibrated) FP8 activation scale; block scales →\npre-quantized ``A``. ``Bs`` is the weight block scale. ``a_global_scale``/``b_global_scale`` are the\ntwo-level NVFP4 per-tensor second-level scales (calibrated ``input_scale`` ``g_a`` and\n``weight_scale_2`` ``g_b``) — provided, never computed; the op folds ``g_a·g_b`` onto the\naccumulator (``a_global_scale`` rides raw ``A`` or a pre-quantized ``As`` alike).\n``output_global_scale`` (NVFP4 requant only) is the NEXT proj's provided ``input_scale``:\nthe fused requant normalizes the GLU intermediate by it, returning ``(C, Cs)`` the down-proj\nconsumes as ``As=Cs, a_global_scale=output_global_scale``.\n\n``activation_format`` is the activations' quantization: ``None`` (default) = the weights' own\nformat, ``\"bf16\"`` = weight-only (no activation quant), or an explicit ``\"fp8\"`` / ``\"mxfp8\"`` /\n``\"mxfp4\"`` / ``\"nvfp4\"`` (``\"mxfp8\"`` on MXFP4 weights = the W4A8 chain; ``check_activation_format``\nhas the per-family matrix). ``gate=True`` reads ``B`` as the interleaved ``(2N, K)`` gate|up weight and\nfuses the ``act_fn`` GLU (``swiglu_alpha``/``swiglu_limit`` its clamped variant), returning the\n``[..., N]`` intermediate (``act_fn=None``: the raw ``[..., 2N]`` gate|up output instead); ``quantize_output=True`` (MX weights only) stores that intermediate in\n``activation_format`` and returns ``(C, Cs)`` for the next op.\n\nRoutes by weight dtype + inferred block:\n- ``Bs`` None → full-precision.\n- MX/NVFP4 (int8/E4M3 weights with UE8M0 group-32 or E4M3 group-16 ``Bs``) →\n ``mx_dynamic_matmul``.\n- tensor-wide FP8 (scalar ``Bs``) → ``w8a8_tensor_dynamic_fp8_matmul``.\n- block FP8 → the static variant when ``As`` is a per-tensor scalar, else dynamic.\n- CSF-compressed NVFP4 weight scales (``prepare_nvfp4_csf_scales``): ``Bs`` is the fixed\n stream, ``b_scale_exceptions``/``b_scale_exception_offsets`` its exceptions and expert\n offsets; the op decodes them before the GEMM.",
11
  "signature": {
12
  "parameters": [
13
  {
 
100
  "default": "None",
101
  "annotation": "torch.Tensor | None"
102
  },
103
+ {
104
+ "name": "b_scale_exceptions",
105
+ "kind": "KEYWORD_ONLY",
106
+ "default": "None",
107
+ "annotation": "torch.Tensor | None"
108
+ },
109
+ {
110
+ "name": "b_scale_exception_offsets",
111
+ "kind": "KEYWORD_ONLY",
112
+ "default": "None",
113
+ "annotation": "torch.Tensor | None"
114
+ },
115
  {
116
  "name": "output_global_scale",
117
  "kind": "KEYWORD_ONLY",
 
125
  {
126
  "name": "matmul_batched",
127
  "qualname": "matmul_batched",
128
+ "module": "_finegrained_kernels_xpu_bbd13a8.batched",
129
  "kind": "function",
130
+ "doc": "Batched matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4, or full-precision). Routes one\nprogram per routed row (``expert_ids`` gives its expert).\n\n``As`` marks ``A`` as already quantized (framework-precomputed scales, or a requantized\nintermediate handed to the down projection); a per-tensor scalar ``As`` is instead the static\n(calibrated) activation scale for block-scale FP8 weights — the op quantizes raw ``A`` against\nit; ``None`` = raw ``A``, quantized dynamically by the op in ``activation_format`` (``None`` =\nthe weights' own format — fp8/E4M3 offline for bd/tensor, inline for MX; ``\"bf16\"`` = weight-only;\n``\"mxfp4\"`` = packed E2M1 activations). ``Bs`` ``None`` = unquantized BF16/FP16 weights.\n``quantize_output`` requantizes the output into ``activation_format`` — the return is then\n``(C, Cs)``. ``gate``/``act_fn``/``swiglu_alpha``/``swiglu_limit`` fuse the gate|up GLU into the\nepilogue; ``act_fn=None`` with ``gate`` skips it, returning the raw interleaved gate|up\noutput for a host-side activation.\n``As``/``Bs`` are each a bare block-scale tensor; the two-level NVFP4\nsecond-level scales ride the separate ``a_global_scale``/``b_global_scale`` (fp32 per-tensor,\nweights per-expert ``(E,)``; from ``nvfp4_quantize_two_level``), and the op folds ``g_a · g_b``\nonto the accumulator. The activation global ``g_a`` is CALIBRATED (the checkpoint's\n``input_scale``): ``a_global_scale=g_a`` with a raw ``A`` has the op quantize ``A / g_a`` per\nblock, and rides a pre-quantized ``As`` the same way. Under an NVFP4 requant the\nfused requant normalizes the GLU intermediate by the PROVIDED ``output_global_scale`` (the next\nproj's calibrated ``input_scale``) before the block quant and returns ``[C, Cs]``; the down\nconsumes it as ``As=Cs, a_global_scale=output_global_scale``. ``gather_idx``/``scatter_idx`` (each None or a ``(S,)`` map)\naddress the source row of ``A`` / destination row of ``C`` per program — None means row\n``s``; the gather lets the gate_up read unexpanded activations (source row\n``s // num_top_k``) with no copy.\n\nRoutes by what the weight tensors themselves say (there is no ``block_size``\nparameter — the quantization block is derived from the scale shape,\n``weight_block_size``):\n- ``Bs`` None → ``full_precision_matmul_batched`` (plain dot, no scales anywhere).\n- MX weights — ``int8`` (packed E2M1) or ``float8_e4m3fn`` (E4M3) with UE8M0\n group-32 ``Bs`` → ``mx_dynamic_matmul_batched``.\n- one scale per expert (``Bs`` ``(E,)``/``(E, 1, 1)``) →\n ``w8a8_tensor_dynamic_fp8_matmul_batched``.\n- block scales (``Bs`` ``(E, N/bn, K/bk)``) → ``w8a8_block_dynamic_fp8_matmul_batched``.\n- CSF-compressed NVFP4 weight scales (``prepare_nvfp4_csf_scales``): ``Bs`` is the fixed\n stream, ``b_scale_exceptions``/``b_scale_exception_offsets`` its exceptions and expert\n offsets; the op decodes them before the GEMM (only the routed experts when routing allows).",
131
  "signature": {
132
  "parameters": [
133
  {
 
238
  "default": "None",
239
  "annotation": "torch.Tensor | None"
240
  },
241
+ {
242
+ "name": "b_scale_exceptions",
243
+ "kind": "KEYWORD_ONLY",
244
+ "default": "None",
245
+ "annotation": "torch.Tensor | None"
246
+ },
247
+ {
248
+ "name": "b_scale_exception_offsets",
249
+ "kind": "KEYWORD_ONLY",
250
+ "default": "None",
251
+ "annotation": "torch.Tensor | None"
252
+ },
253
  {
254
  "name": "output_global_scale",
255
  "kind": "KEYWORD_ONLY",
 
263
  {
264
  "name": "matmul_grouped",
265
  "qualname": "matmul_grouped",
266
+ "module": "_finegrained_kernels_xpu_bbd13a8.grouped",
267
  "kind": "function",
268
+ "doc": "Grouped matmul dispatcher (W8A8 FP8, W4A8/W4A4 FP4, or full-precision).\n``expert_start`` is the ``(E+1,)`` tiling schedule from one ``compute_grouped_scheduling``\npass, shared by every grouped GEMM of the layer (the expert sort is virtual — nothing is\nphysically permuted).\n\n``As`` marks ``A`` as already quantized (framework-precomputed scales, or a requantized\nintermediate handed to the down projection); a per-tensor scalar ``As`` is instead the static\n(calibrated) activation scale for block-scale FP8 weights — the op quantizes raw ``A`` against\nit; ``None`` = raw ``A``, quantized dynamically by the op in ``activation_format`` (``None`` =\nthe weights' own format — fp8/E4M3, or the fp4 chains; ``\"bf16\"`` = weight-only; ``\"mxfp4\"`` =\npacked E2M1 activations). ``Bs`` ``None`` = unquantized BF16/FP16 weights.\n``quantize_output`` requantizes the output into ``activation_format`` — the return is then\n``(C, Cs)``. ``gate``/``act_fn``/``swiglu_alpha``/``swiglu_limit`` fuse the gate|up GLU into the\nepilogue; ``act_fn=None`` with ``gate`` skips it, returning the raw interleaved gate|up\noutput for a host-side activation.\n``As``/``Bs`` are each a bare block-scale tensor; the two-level NVFP4 second-level scales ride\nthe separate ``a_global_scale``/``b_global_scale`` (fp32 per-tensor, weights per-expert ``(E,)``;\nfrom ``nvfp4_quantize_two_level``), and the op folds ``g_a · g_b`` onto the accumulator. The\nactivation global ``g_a`` is CALIBRATED (the checkpoint's ``input_scale``): ``a_global_scale=g_a``\nwith a raw ``A`` has the op quantize ``A / g_a`` per block, and rides a pre-quantized ``As`` the\nsame way. Under an NVFP4 requant the fused requant normalizes the GLU intermediate by the\nPROVIDED ``output_global_scale`` (the next proj's calibrated ``input_scale``) before the block\nquant and returns ``[C, Cs]``; the down consumes it as ``As=Cs, a_global_scale=output_global_scale``.\nRow order is carried by the standalone maps: ``gather_idx`` gathers ``A`` (``None`` ->\nalready expert-ordered), ``scatter_idx`` scatters the output. The fused MoE chain is one\nscheduling pass: gate_up with ``scatter_idx=None`` + ``gate=True`` + ``quantize_output=True``,\nthen down with ``gather_idx=None`` and the\nintermediate's scales as ``As``. EP-sentinel routes sit past ``expert_start[-1]``, which\nno tile reaches.\n\nRoutes by what the weight tensors themselves say (there is no ``block_size``\nparameter — the quantization block is derived from the scale shape,\n``weight_block_size``):\n- ``Bs`` None → ``full_precision_matmul_grouped`` (plain dot, no scales anywhere).\n- MX weights — ``int8`` (packed E2M1) or ``float8_e4m3fn`` (E4M3) with UE8M0\n group-32 ``Bs`` → ``mx_dynamic_matmul_grouped``.\n- one scale per expert (``Bs`` ``(E,)``/``(E, 1, 1)``) →\n ``w8a8_tensor_dynamic_fp8_matmul_grouped``.\n- block scales (``Bs`` ``(E, N/bn, K/bk)``) → ``w8a8_block_dynamic_fp8_matmul_grouped``.\n- CSF-compressed NVFP4 weight scales (``prepare_nvfp4_csf_scales``): ``Bs`` is the fixed\n stream, ``b_scale_exceptions``/``b_scale_exception_offsets`` its exceptions and expert\n offsets; the op decodes them before the GEMM (only the routed experts when routing allows).",
269
  "signature": {
270
  "parameters": [
271
  {
 
376
  "default": "None",
377
  "annotation": "torch.Tensor | None"
378
  },
379
+ {
380
+ "name": "b_scale_exceptions",
381
+ "kind": "KEYWORD_ONLY",
382
+ "default": "None",
383
+ "annotation": "torch.Tensor | None"
384
+ },
385
+ {
386
+ "name": "b_scale_exception_offsets",
387
+ "kind": "KEYWORD_ONLY",
388
+ "default": "None",
389
+ "annotation": "torch.Tensor | None"
390
+ },
391
  {
392
  "name": "output_global_scale",
393
  "kind": "KEYWORD_ONLY",
 
401
  {
402
  "name": "moe_fused_batched",
403
  "qualname": "moe_fused_batched",
404
+ "module": "_finegrained_kernels_xpu_bbd13a8.moe",
405
  "kind": "function",
406
+ "doc": "Fused batched MoE (decode): gate_up + SiLU + requant epilogue → per-row quantized\nintermediate → batched down → routing-weighted top-k reduce. Returns\n``(num_tokens, hidden_dim)``. The base ops dispatch on the weight dtypes / scale\nlayout (block-dynamic FP8, MXFP8/MXFP4, NVFP4 — decode runs the software/swap arms\nbelow the native mxf4nvf4 M=128 staging); ``activation_format`` names the activation\nquantization for the whole block — activations and the fused intermediate requant\ncarry it (``\"mxfp4\"`` runs the all-fp4 W4A4 chain, ``\"bf16\"`` is weight-only); ``None``\nfollows the weight format, and the ops validate the pairing. The\n``*_proj_input_global_scale`` pair is the NVFP4 activation second level (a checkpoint's\ncalibrated per-projection ``input_scale``): the gate_up quantizes hidden against its own,\nrequants the intermediate against the down's, and the down consumes that as its activation\nglobal. ``None`` is dynamic quant everywhere else. ``simulate_unfused`` (testing) rounds each\nstep through the activation dtype so the output matches the unfused reference to\nreduce order. ``act_fn`` is a\n``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any\ncallable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated\nprojection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)\n— the swizzled layout is for the dot_scaled arm; weight-only chains take affine.\n``*_proj_scale_exceptions``/``*_proj_scale_exception_offsets`` mark that projection's\n``*_proj_scale_inv`` as a CSF-compressed NVFP4 fixed stream (``prepare_nvfp4_csf_scales``);\nthe block decodes it, only the routed experts, before its GEMMs.",
407
  "signature": {
408
  "parameters": [
409
  {
 
448
  "default": null,
449
  "annotation": "torch.Tensor"
450
  },
451
+ {
452
+ "name": "gate_up_proj_scale_exceptions",
453
+ "kind": "POSITIONAL_OR_KEYWORD",
454
+ "default": "None",
455
+ "annotation": "torch.Tensor | None"
456
+ },
457
+ {
458
+ "name": "gate_up_proj_scale_exception_offsets",
459
+ "kind": "POSITIONAL_OR_KEYWORD",
460
+ "default": "None",
461
+ "annotation": "torch.Tensor | None"
462
+ },
463
+ {
464
+ "name": "down_proj_scale_exceptions",
465
+ "kind": "POSITIONAL_OR_KEYWORD",
466
+ "default": "None",
467
+ "annotation": "torch.Tensor | None"
468
+ },
469
+ {
470
+ "name": "down_proj_scale_exception_offsets",
471
+ "kind": "POSITIONAL_OR_KEYWORD",
472
+ "default": "None",
473
+ "annotation": "torch.Tensor | None"
474
+ },
475
  {
476
  "name": "gate_up_proj_weight_global_scale",
477
  "kind": "POSITIONAL_OR_KEYWORD",
 
581
  {
582
  "name": "moe_fused_grouped",
583
  "qualname": "moe_fused_grouped",
584
+ "module": "_finegrained_kernels_xpu_bbd13a8.moe",
585
  "kind": "function",
586
+ "doc": "Fused grouped MoE (prefill): gather gate_up + SiLU + requant epilogue → quantized\nexpert-ordered intermediate → grouped down → routing-weighted top-k reduce. Returns\n``(num_tokens, hidden_dim)``. The base ops dispatch on the weight dtypes / scale\nlayout (block-dynamic FP8, MXFP8/MXFP4, NVFP4); ``activation_format`` names the activation\nquantization for the whole block — activations and the fused intermediate requant\ncarry it (``\"mxfp4\"``/``\"nvfp4\"`` run all-fp4 W4A4 chains, ``\"bf16\"`` is weight-only);\n``None`` follows the weight format, and the ops validate the pairing. The\n``*_proj_input_global_scale`` pair is the NVFP4 activation second level (a checkpoint's\ncalibrated per-projection ``input_scale``): the gate_up quantizes hidden against its own,\nrequants the intermediate against the down's, and the down consumes that as its activation\nglobal. ``None`` is dynamic quant everywhere else. ``simulate_unfused`` (testing) rounds each step through\nthe activation dtype so the output matches the unfused reference to reduce order. ``act_fn`` is a\n``get_supported_act_fns()`` name (fused into the gate_up epilogue where the forward fuses) or any\ncallable applied on the host to the raw gate_up output; ``gate=False`` runs an ungated\nprojection. Scales are affine or pre-swizzled (``SWIZZLE_32_4_4``, self-describing 5-D)\n— the swizzled layout is for the dot_scaled arm; weight-only chains take affine.\n``*_proj_scale_exceptions``/``*_proj_scale_exception_offsets`` mark that projection's\n``*_proj_scale_inv`` as a CSF-compressed NVFP4 fixed stream (``prepare_nvfp4_csf_scales``);\nthe block decodes it, only the routed experts, before its GEMMs.",
587
  "signature": {
588
  "parameters": [
589
  {
 
628
  "default": null,
629
  "annotation": "torch.Tensor"
630
  },
631
+ {
632
+ "name": "gate_up_proj_scale_exceptions",
633
+ "kind": "POSITIONAL_OR_KEYWORD",
634
+ "default": "None",
635
+ "annotation": "torch.Tensor | None"
636
+ },
637
+ {
638
+ "name": "gate_up_proj_scale_exception_offsets",
639
+ "kind": "POSITIONAL_OR_KEYWORD",
640
+ "default": "None",
641
+ "annotation": "torch.Tensor | None"
642
+ },
643
+ {
644
+ "name": "down_proj_scale_exceptions",
645
+ "kind": "POSITIONAL_OR_KEYWORD",
646
+ "default": "None",
647
+ "annotation": "torch.Tensor | None"
648
+ },
649
+ {
650
+ "name": "down_proj_scale_exception_offsets",
651
+ "kind": "POSITIONAL_OR_KEYWORD",
652
+ "default": "None",
653
+ "annotation": "torch.Tensor | None"
654
+ },
655
  {
656
  "name": "gate_up_proj_weight_global_scale",
657
  "kind": "POSITIONAL_OR_KEYWORD",
 
761
  {
762
  "name": "embedding_lookup",
763
  "qualname": "embedding_lookup",
764
+ "module": "_finegrained_kernels_xpu_bbd13a8.embedding",
765
  "kind": "function",
766
  "doc": "Gather and dequantize selected rows without expanding the embedding table.\n\n``weight_format`` selects ``fp8``, ``nvfp4``, ``mxfp8``, ``mxfp4``, ``int8``, or ``int4``.\nBy default, a global scale selects NVFP4, signed int8 weights select INT8, and otherwise\nFP8 is used. FP8 accepts scalar, per-row, or square block scales (``block_size``).\nNVFP4 uses E4M3 group-16 scales and one FP32 multiplier; MX formats use UE8M0 group-32\nscales. FP4 packs adjacent columns, low nibble first. INT8 uses per-row scales; INT4\npacks adjacent vocabulary rows and uses per-row column groups inferred from its scale\ngrid. Integer values are signed, symmetric, and have no zero point.\n\nOutputs default to the floating scale dtype, or bf16 for NVFP4/MX. Table/grid strides\nmay describe TP slices. Indices follow ``torch.nn.functional.embedding``: negative and\nout-of-range values fail; padding indices look up their stored row. Empty, repeated,\nand noncontiguous indices work.",
767
  "signature": {
 
815
  {
816
  "name": "get_supported_act_fns",
817
  "qualname": "get_supported_act_fns",
818
+ "module": "_finegrained_kernels_xpu_bbd13a8.formats",
819
  "kind": "function",
820
  "doc": "The activation names the gate|up epilogue fuses in-kernel; any other activation is applied\non the host by the MoE forwards (``act_fn`` as a callable).",
821
  "signature": {
 
826
  {
827
  "name": "get_supported_norms",
828
  "qualname": "get_supported_norms",
829
+ "module": "_finegrained_kernels_xpu_bbd13a8.norm",
830
  "kind": "function",
831
  "doc": "The norm names the kernels fuse (``post_expert_norm``), each ``x * factor * rsqrt(mean +\neps)`` over the row: ``\"rms_norm\"`` scales the normalized row by ``weight``,\n``\"centered_rms_norm\"`` by ``1 + weight`` (the zero-centered parameterization), and\n``\"input_scaled_rms_norm\"`` scales by ``1 + weight`` BEFORE normalizing, so the mean square\nis taken on the scaled row. Anything else stays a host callable.",
832
  "signature": {
 
837
  {
838
  "name": "rms_norm_rows",
839
  "qualname": "rms_norm_rows",
840
+ "module": "_finegrained_kernels_xpu_bbd13a8.norm",
841
  "kind": "function",
842
  "doc": "RMS-normalize ``(S, H)`` rows in one launch, in the ``get_supported_norms()`` form named by\n``norm`` (fp32 accumulate, input dtype out). The MoE chain folds this into\n``weighted_reduce`` instead; this is the standalone form.",
843
  "signature": {
 
873
  {
874
  "name": "swizzle_mx_scales",
875
  "qualname": "swizzle_mx_scales",
876
+ "module": "_finegrained_kernels_xpu_bbd13a8.swizzle",
877
  "kind": "function",
878
  "doc": "Reorder a block-scale tensor into the ``SWIZZLE_32_4_4`` layout the Blackwell tcgen05\nscaled-MMA consumes, one triton launch per matrix (``_swizzle_scales_kernel`` — no torch\npermute/transpose copies). The scale values are unchanged — this only rearranges them from\nplain row-major into the swizzled order the tensor core reads directly (the same layout\ncuBLAS/CUTLASS require for MXFP8/NVFP4 ``scaled_mm``). Plain row-major forces a gather that\ncaps the scaled dot below the fp8/fp4 peak; the swizzle removes it. Apply to weight scales\nonce at model load; the ops accept the result directly.\n\n``scale`` is the per-block scale grid — UE8M0 (``float8_e8m0fnu``, group-32 MXFP8/MXFP4) or\nE4M3 (``float8_e4m3fn``, group-16 NVFP4); the reorder is dtype-agnostic (moves bytes):\n\n- 2D ``(rows, K // group)``: one matrix (a dense weight's scale).\n- 3D ``(E, rows, K // group)``: an expert stack, each expert swizzled independently so its\n blocks stay ``ceil(rows/128)``-aligned (the reader indexes expert ``e`` at\n ``e * ceil(rows/128)``; byte-identical to a flat swizzle when ``rows % 128 == 0``).\n\n``gather_idx`` (2D only): a 1-D ``(padded_rows,)`` index mapping each output (sorted) row to\nits source row in ``scale`` (``-1`` = padding → zero row), folded into the kernel's load — the\nrouted/expert-sorted, per-tile-padded layout a grouped GEMM reads affine per BM=128 tile.\n``padded_rows`` must be a multiple of 128.\n\n``rows``/``cols`` are zero-padded to (128, 4) multiples; returns the 5D\n``(G, row_blocks, ceil(cols/4), 2, 256)`` artifact the ops read — ``G`` the expert count (1 for\na matrix), so an expert stack shards/gathers on its leading dim. Bit-identical to CUTLASS's\npacker (verified).",
879
  "signature": {
 
897
  {
898
  "name": "unswizzle_mx_scales",
899
  "qualname": "unswizzle_mx_scales",
900
+ "module": "_finegrained_kernels_xpu_bbd13a8.swizzle",
901
  "kind": "function",
902
  "doc": "Inverse of ``swizzle_mx_scales``: a SWIZZLE_32_4_4 artifact back to the plain row-major\n``(rows, cols)`` grid — or ``(num_experts, rows, cols)`` for an expert stack — with the\n(128, 4) padding trimmed. Pure reshape/permute on the byte view (no kernel); it runs at\nsave/dequantize time, never on a forward, so the torch-level cost is irrelevant.\n\n``rows``/``cols`` are the LOGICAL dims of ONE matrix (for a gate|up slab, the full ``2N``);\nboth are trimmed back out of the (128, 4) padding. ``num_experts`` selects the stacked\n``(E, rows, cols)`` result and must match the artifact's leading dim.",
903
  "signature": {
 
930
  "return_annotation": "torch.Tensor"
931
  }
932
  },
933
+ {
934
+ "name": "prepare_nvfp4_csf_scales",
935
+ "qualname": "prepare_nvfp4_csf_scales",
936
+ "module": "_finegrained_kernels_xpu_bbd13a8.loading.scales",
937
+ "kind": "function",
938
+ "doc": "Prepare one matrix or an expert stack without expanding or moving its scales.\n\nCSF stores each row of E4M3 scale bytes as a base plus 4-bit deltas, which is\nlossless whenever a row's bytes span at most 16 codes; the rest are exceptions.\n\n- `fixed` is uint8 `[rows/16, 16*(1+cols/2)]`, or the same shape with a leading\n expert dimension. Each 16-row slab holds 16 row bases (bytes 0..240), then those\n rows' deltas, two per byte (even column in the low nibble). Scale `(r, c)` decodes\n to byte `base[r] + delta[r, c]`.\n- `exceptions` is one uint32 `[count]` tensor for a matrix, or one per expert, for\n the scales outside their row's window. Each word is `position | byte << 24`:\n the low 24 bits are the row-major index `r * cols + c` (sorted and unique), the\n high 8 bits are the exact E4M3 byte, which overwrites the decoded value.\n\nReturns, on the input device:\n\n- `fixed`: contiguous `[experts, rows/16, 16*(1+cols/2)]` (a 2D input gains `experts=1`).\n- `exceptions`: every expert's words concatenated into one uint32 vector.\n- `expert_offsets`: uint32 `[experts + 1]` prefix sums; expert `e` owns\n `exceptions[expert_offsets[e]:expert_offsets[e + 1]]`.\n\nThese are `decompress_nvfp4_csf_scales`' inputs. Decode on the accelerator at load time\nfor dense residency, or into shared scratch immediately before GEMM. The checks here\nrun once per checkpoint load, off the forward path, so the decoder does not repeat them.",
939
+ "signature": {
940
+ "parameters": [
941
+ {
942
+ "name": "fixed",
943
+ "kind": "POSITIONAL_OR_KEYWORD",
944
+ "default": null,
945
+ "annotation": "torch.Tensor"
946
+ },
947
+ {
948
+ "name": "exceptions",
949
+ "kind": "POSITIONAL_OR_KEYWORD",
950
+ "default": null,
951
+ "annotation": "torch.Tensor | collections.abc.Sequence[torch.Tensor]"
952
+ }
953
+ ],
954
+ "return_annotation": "tuple[torch.Tensor, torch.Tensor, torch.Tensor]"
955
+ }
956
+ },
957
+ {
958
+ "name": "decompress_nvfp4_csf_scales",
959
+ "qualname": "decompress_nvfp4_csf_scales",
960
+ "module": "_finegrained_kernels_xpu_bbd13a8.loading.scales",
961
+ "kind": "function",
962
+ "doc": "Decode prepared CSF streams to dense E4M3 scales for an ordinary NVFP4 GEMM.\n\nWith no `out`, allocate dense scales on the accelerator at checkpoint loading.\nPass reusable contiguous [experts, rows, cols] workspace to keep the streams\ncompressed between layers. Consume the workspace before overwriting it; it\nmust not be retained for backward or shared by concurrent consumers.\nA shared dense workspace saves memory across layers, not within one layer.\nPass the grouped GEMM's cumulative `expert_start` to decode only experts with\nrouted tokens. Inactive workspace planes stay untouched and must not be read.\n\nThe streams must come from `prepare_nvfp4_csf_scales`, which validates them; only\n`out` and `expert_start`, which are new here, are checked.",
963
+ "signature": {
964
+ "parameters": [
965
+ {
966
+ "name": "fixed",
967
+ "kind": "POSITIONAL_OR_KEYWORD",
968
+ "default": null,
969
+ "annotation": "torch.Tensor"
970
+ },
971
+ {
972
+ "name": "exceptions",
973
+ "kind": "POSITIONAL_OR_KEYWORD",
974
+ "default": null,
975
+ "annotation": "torch.Tensor"
976
+ },
977
+ {
978
+ "name": "expert_offsets",
979
+ "kind": "POSITIONAL_OR_KEYWORD",
980
+ "default": null,
981
+ "annotation": "torch.Tensor"
982
+ },
983
+ {
984
+ "name": "out",
985
+ "kind": "KEYWORD_ONLY",
986
+ "default": "None",
987
+ "annotation": "torch.Tensor | None"
988
+ },
989
+ {
990
+ "name": "expert_start",
991
+ "kind": "KEYWORD_ONLY",
992
+ "default": "None",
993
+ "annotation": "torch.Tensor | None"
994
+ }
995
+ ],
996
+ "return_annotation": "torch.Tensor"
997
+ }
998
+ },
999
  {
1000
  "name": "mxfp8_act_quant",
1001
  "qualname": "mxfp8_act_quant",
1002
+ "module": "_finegrained_kernels_xpu_bbd13a8.quant",
1003
  "kind": "function",
1004
  "doc": "Quantize ``(T, K)`` activations to MX once (E4M3 values + UE8M0 group-32 uint8 scales)\ninstead of inline per weight-tile — the fused gate_up re-ran the inline quant per N-tile\n(16x redundant amax/convert ALU + 2x act bytes), which held it at ~380 TFLOPS while the\npre-quantized down kernel ran at ~1080. One pass costs ~50µs at 8k tokens. Bit-exact with\nthe inline form (same group boundaries). ``swizzled=True`` emits the scale directly in\nSWIZZLE_32_4_4 for the tcgen05 fast path (same dense grid, per-element store).",
1005
  "signature": {
 
1023
  {
1024
  "name": "mxfp4_act_quant",
1025
  "qualname": "mxfp4_act_quant",
1026
+ "module": "_finegrained_kernels_xpu_bbd13a8.quant",
1027
  "kind": "function",
1028
  "doc": "Quantize ``(T, K)`` activations to MXFP4 in one kernel pass: packed-E2M1 values\n(``(T, K//2)`` int8, two codes per byte, first value in the low nibble) + UE8M0\ngroup-32 uint8 scales (``(T, K//32)``, amax/6 ceil'd to a power of two). Bit-identical\nto the fused epilogues' inline form (shared ``mx_act_quant_inline`` arm). Feeds the\nW4A4 arm of the MX matmul ops; quantizing activations to fp4 at runtime is an\naccuracy call the caller owns — the ops never do it implicitly. ``swizzled=True`` emits the\nscale directly in SWIZZLE_32_4_4 for the tcgen05 fast path.",
1029
  "signature": {
 
1047
  {
1048
  "name": "nvfp4_act_quant",
1049
  "qualname": "nvfp4_act_quant",
1050
+ "module": "_finegrained_kernels_xpu_bbd13a8.quant",
1051
  "kind": "function",
1052
  "doc": "Quantize ``(T, K)`` activations to NVFP4 in one kernel pass: packed-E2M1 values\n(``(T, K//2)`` int8) + E4M3 group-16 block scales (``(T, K//16)`` — ``amax/6`` rounded to\nE4M3, NOT a power of two; values divide by the DECODED scale before the E2M1 grid,\nthe standard two-step). ``global_scale`` is the CALIBRATED per-tensor second level\n(fp32, the checkpoint's ``input_scale``): values are normalized by it before\nthe block quant, so block scales stay in e4m3 range regardless of the activation's\ndynamic range — the canonical two-level format. The GEMM folds ``g_a·g_b`` back onto\nthe accumulator (pass ``As=scales`` with ``a_global_scale=global_scale``). Per-expert globals\nneed each row's expert, which ``expert_index`` gives where the caller already holds that map\n(the batched op's ``expert_ids``, sentinels and all) — it is read only when the globals are\nper expert, and ``mx_act_quant_grouped`` needs none at all, its tiles carrying an expert.\n``None`` = single-level (``g_a = 1``). ``swizzled=True`` emits the scale directly in\nSWIZZLE_32_4_4 for the tcgen05 fast path.",
1053
  "signature": {