Uploaded using `kernel-builder`.
Browse files- build/torch211-cxx11-cu128-x86_64-linux/__init__.py +11 -3
- build/torch211-cxx11-cu128-x86_64-linux/{_minimaxai_msa_blackwell_cuda_58018d1.abi3.so → _minimaxai_msa_blackwell_cuda_25b0067.abi3.so} +2 -2
- build/torch211-cxx11-cu128-x86_64-linux/_native.py +195 -1
- build/torch211-cxx11-cu128-x86_64-linux/_ops.py +3 -3
- build/torch211-cxx11-cu128-x86_64-linux/api_status.py +4 -3
- build/torch211-cxx11-cu128-x86_64-linux/decode/topk_sparse.py +20 -0
- build/torch211-cxx11-cu128-x86_64-linux/interface.py +38 -3
- build/torch211-cxx11-cu128-x86_64-linux/metadata.json +8 -8
- build/torch211-cxx11-cu130-x86_64-linux/__init__.py +11 -3
- build/torch211-cxx11-cu130-x86_64-linux/{_minimaxai_msa_blackwell_cuda_58018d1.abi3.so → _minimaxai_msa_blackwell_cuda_25b0067.abi3.so} +2 -2
- build/torch211-cxx11-cu130-x86_64-linux/_native.py +195 -1
- build/torch211-cxx11-cu130-x86_64-linux/_ops.py +3 -3
- build/torch211-cxx11-cu130-x86_64-linux/api_status.py +4 -3
- build/torch211-cxx11-cu130-x86_64-linux/decode/topk_sparse.py +20 -0
- build/torch211-cxx11-cu130-x86_64-linux/interface.py +38 -3
- build/torch211-cxx11-cu130-x86_64-linux/metadata.json +8 -8
- build/torch212-cxx11-cu130-x86_64-linux/__init__.py +11 -3
- build/torch212-cxx11-cu130-x86_64-linux/{_minimaxai_msa_blackwell_cuda_58018d1.abi3.so → _minimaxai_msa_blackwell_cuda_25b0067.abi3.so} +2 -2
- build/torch212-cxx11-cu130-x86_64-linux/_native.py +195 -1
- build/torch212-cxx11-cu130-x86_64-linux/_ops.py +3 -3
- build/torch212-cxx11-cu130-x86_64-linux/api_status.py +4 -3
- build/torch212-cxx11-cu130-x86_64-linux/decode/topk_sparse.py +20 -0
- build/torch212-cxx11-cu130-x86_64-linux/interface.py +38 -3
- build/torch212-cxx11-cu130-x86_64-linux/metadata.json +8 -8
- build/torch212-cxx11-cu132-x86_64-linux/__init__.py +11 -3
- build/torch212-cxx11-cu132-x86_64-linux/{_minimaxai_msa_blackwell_cuda_58018d1.abi3.so → _minimaxai_msa_blackwell_cuda_25b0067.abi3.so} +2 -2
- build/torch212-cxx11-cu132-x86_64-linux/_native.py +195 -1
- build/torch212-cxx11-cu132-x86_64-linux/_ops.py +3 -3
- build/torch212-cxx11-cu132-x86_64-linux/api_status.py +4 -3
- build/torch212-cxx11-cu132-x86_64-linux/decode/topk_sparse.py +20 -0
- build/torch212-cxx11-cu132-x86_64-linux/interface.py +38 -3
- build/torch212-cxx11-cu132-x86_64-linux/metadata.json +8 -8
build/torch211-cxx11-cu128-x86_64-linux/__init__.py
CHANGED
|
@@ -7,9 +7,12 @@ MiniMax-M3 decode-sparse attention path used by FlashRT's MiniMax Spark runtime.
|
|
| 7 |
|
| 8 |
Implementation status:
|
| 9 |
* native CUDA helper: score -> top-k sparse block ids;
|
| 10 |
-
*
|
|
|
|
|
|
|
|
|
|
| 11 |
* MiniMaxAI/msa compatibility wrappers for CSR prefill, decode, NVFP4 helpers,
|
| 12 |
-
and FP4 block-score
|
| 13 |
|
| 14 |
The upstream MiniMaxAI/msa package is SM100-only; this package is the Blackwell
|
| 15 |
extension path. The public API is Tensor-oriented and independent from
|
|
@@ -48,7 +51,11 @@ from .interface import (
|
|
| 48 |
sparse_atten_nvfp4_kv_func,
|
| 49 |
sparse_decode_atten_func,
|
| 50 |
)
|
| 51 |
-
from ._native import
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
from .naive.flash_with_topk_idx import naive_flash_decode_with_topk_idx
|
| 53 |
from .naive.topk_sparse import naive_flash_decode_with_gqa_share_sparse
|
| 54 |
from .quantize import (
|
|
@@ -88,6 +95,7 @@ __all__ = [
|
|
| 88 |
"flash_decode_with_gqa_share_sparse",
|
| 89 |
"has_native_ops",
|
| 90 |
"native_topk_from_scores",
|
|
|
|
| 91 |
"naive_flash_decode_with_gqa_share_sparse",
|
| 92 |
"naive_flash_decode_with_topk_idx",
|
| 93 |
"get_cu_seqblocks",
|
|
|
|
| 7 |
|
| 8 |
Implementation status:
|
| 9 |
* native CUDA helper: score -> top-k sparse block ids;
|
| 10 |
+
* native CUDA tensor-core sparse decode for the MiniMax-M3 Blackwell shape;
|
| 11 |
+
* native CUDA FP4 block-score indexer;
|
| 12 |
+
* native CUDA helper: swizzled NVFP4 -> BF16 dequant for the W4A16 quality path;
|
| 13 |
+
* Blackwell-validated sparse prefill path;
|
| 14 |
* MiniMaxAI/msa compatibility wrappers for CSR prefill, decode, NVFP4 helpers,
|
| 15 |
+
and FP4 block-score helpers.
|
| 16 |
|
| 17 |
The upstream MiniMaxAI/msa package is SM100-only; this package is the Blackwell
|
| 18 |
extension path. The public API is Tensor-oriented and independent from
|
|
|
|
| 51 |
sparse_atten_nvfp4_kv_func,
|
| 52 |
sparse_decode_atten_func,
|
| 53 |
)
|
| 54 |
+
from ._native import (
|
| 55 |
+
has_native_ops,
|
| 56 |
+
native_nvfp4_dequant_swizzled_to_bf16,
|
| 57 |
+
native_topk_from_scores,
|
| 58 |
+
)
|
| 59 |
from .naive.flash_with_topk_idx import naive_flash_decode_with_topk_idx
|
| 60 |
from .naive.topk_sparse import naive_flash_decode_with_gqa_share_sparse
|
| 61 |
from .quantize import (
|
|
|
|
| 95 |
"flash_decode_with_gqa_share_sparse",
|
| 96 |
"has_native_ops",
|
| 97 |
"native_topk_from_scores",
|
| 98 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 99 |
"naive_flash_decode_with_gqa_share_sparse",
|
| 100 |
"naive_flash_decode_with_topk_idx",
|
| 101 |
"get_cu_seqblocks",
|
build/torch211-cxx11-cu128-x86_64-linux/{_minimaxai_msa_blackwell_cuda_58018d1.abi3.so → _minimaxai_msa_blackwell_cuda_25b0067.abi3.so}
RENAMED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:528883873873d9a482cbe93eb0ea0ec5be7f0eac009dd8b103a0609841c032d5
|
| 3 |
+
size 446928
|
build/torch211-cxx11-cu128-x86_64-linux/_native.py
CHANGED
|
@@ -62,4 +62,198 @@ def native_topk_from_scores(
|
|
| 62 |
return out
|
| 63 |
|
| 64 |
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
return out
|
| 63 |
|
| 64 |
|
| 65 |
+
if _HAS_NATIVE_OPS:
|
| 66 |
+
|
| 67 |
+
@torch.library.register_fake(
|
| 68 |
+
add_op_namespace_prefix("msa_decode_sparse_attn_mma_paged")
|
| 69 |
+
)
|
| 70 |
+
def _msa_decode_sparse_attn_mma_paged_fake(
|
| 71 |
+
q: torch.Tensor,
|
| 72 |
+
k_cache: torch.Tensor,
|
| 73 |
+
v_cache: torch.Tensor,
|
| 74 |
+
req_to_token: torch.Tensor,
|
| 75 |
+
seq_lens: torch.Tensor,
|
| 76 |
+
slot_ids: torch.Tensor,
|
| 77 |
+
topk_idx: torch.Tensor,
|
| 78 |
+
block_size: int,
|
| 79 |
+
sm_scale: float,
|
| 80 |
+
out: torch.Tensor,
|
| 81 |
+
) -> None:
|
| 82 |
+
return None
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def native_decode_mma_supported(
|
| 86 |
+
q: torch.Tensor,
|
| 87 |
+
k_cache: torch.Tensor,
|
| 88 |
+
*,
|
| 89 |
+
block_size: int,
|
| 90 |
+
) -> bool:
|
| 91 |
+
"""Whether the tensor-core decode kernel applies to these inputs.
|
| 92 |
+
|
| 93 |
+
The mma kernel is specialized for the M3 MSA shape: head_dim 128, GQA
|
| 94 |
+
group (Hq/Hkv) 16, bf16, and a block size that is a multiple of 64.
|
| 95 |
+
"""
|
| 96 |
+
|
| 97 |
+
if not _HAS_NATIVE_OPS:
|
| 98 |
+
return False
|
| 99 |
+
if q.dtype is not torch.bfloat16 or k_cache.dtype is not torch.bfloat16:
|
| 100 |
+
return False
|
| 101 |
+
if q.dim() != 3 or k_cache.dim() != 3:
|
| 102 |
+
return False
|
| 103 |
+
head_dim = int(q.shape[-1])
|
| 104 |
+
num_q_heads = int(q.shape[1])
|
| 105 |
+
num_kv_heads = int(k_cache.shape[1])
|
| 106 |
+
if head_dim != 128 or num_kv_heads <= 0:
|
| 107 |
+
return False
|
| 108 |
+
if num_q_heads % num_kv_heads != 0 or num_q_heads // num_kv_heads != 16:
|
| 109 |
+
return False
|
| 110 |
+
if int(block_size) % 64 != 0:
|
| 111 |
+
return False
|
| 112 |
+
return True
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def native_decode_sparse_attn_mma_paged(
|
| 116 |
+
q: torch.Tensor,
|
| 117 |
+
k_cache: torch.Tensor,
|
| 118 |
+
v_cache: torch.Tensor,
|
| 119 |
+
req_to_token: torch.Tensor,
|
| 120 |
+
seq_lens: torch.Tensor,
|
| 121 |
+
slot_ids: torch.Tensor,
|
| 122 |
+
block_size: int,
|
| 123 |
+
topk_idx: torch.Tensor,
|
| 124 |
+
sm_scale: float,
|
| 125 |
+
) -> torch.Tensor:
|
| 126 |
+
"""Paged tensor-core block-sparse GQA decode. Returns [B, Hq, D] bf16."""
|
| 127 |
+
|
| 128 |
+
if not _HAS_NATIVE_OPS:
|
| 129 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 130 |
+
out = torch.empty(
|
| 131 |
+
(int(q.shape[0]), int(q.shape[1]), int(q.shape[2])),
|
| 132 |
+
device=q.device,
|
| 133 |
+
dtype=q.dtype,
|
| 134 |
+
)
|
| 135 |
+
ops.msa_decode_sparse_attn_mma_paged(
|
| 136 |
+
q.contiguous(),
|
| 137 |
+
k_cache.contiguous(),
|
| 138 |
+
v_cache.contiguous(),
|
| 139 |
+
req_to_token.contiguous(),
|
| 140 |
+
seq_lens.contiguous(),
|
| 141 |
+
slot_ids.contiguous(),
|
| 142 |
+
topk_idx.contiguous(),
|
| 143 |
+
int(block_size),
|
| 144 |
+
float(sm_scale),
|
| 145 |
+
out,
|
| 146 |
+
)
|
| 147 |
+
return out
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
if _HAS_NATIVE_OPS:
|
| 151 |
+
|
| 152 |
+
@torch.library.register_fake(
|
| 153 |
+
add_op_namespace_prefix("msa_indexer_block_scores")
|
| 154 |
+
)
|
| 155 |
+
def _msa_indexer_block_scores_fake(
|
| 156 |
+
q: torch.Tensor,
|
| 157 |
+
k_pages: torch.Tensor,
|
| 158 |
+
batch_of_q: torch.Tensor,
|
| 159 |
+
cu_q: torch.Tensor,
|
| 160 |
+
cu_k: torch.Tensor,
|
| 161 |
+
cu_pages: torch.Tensor,
|
| 162 |
+
kv_indices: torch.Tensor,
|
| 163 |
+
causal: int,
|
| 164 |
+
scores: torch.Tensor,
|
| 165 |
+
) -> None:
|
| 166 |
+
return None
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
def native_indexer_block_scores(
|
| 170 |
+
q: torch.Tensor,
|
| 171 |
+
k_pages: torch.Tensor,
|
| 172 |
+
batch_of_q: torch.Tensor,
|
| 173 |
+
cu_q: torch.Tensor,
|
| 174 |
+
cu_k: torch.Tensor,
|
| 175 |
+
cu_pages: torch.Tensor,
|
| 176 |
+
kv_indices: torch.Tensor,
|
| 177 |
+
*,
|
| 178 |
+
max_blocks: int,
|
| 179 |
+
causal: bool,
|
| 180 |
+
) -> torch.Tensor:
|
| 181 |
+
"""Block-max QK indexer scores. q/k_pages are bf16 (already dequantized).
|
| 182 |
+
|
| 183 |
+
Returns [Hq, max_blocks, total_q] f32 (-inf where no key is visible).
|
| 184 |
+
"""
|
| 185 |
+
|
| 186 |
+
if not _HAS_NATIVE_OPS:
|
| 187 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 188 |
+
total_q = int(q.shape[0])
|
| 189 |
+
hq = int(q.shape[1])
|
| 190 |
+
scores = torch.full(
|
| 191 |
+
(hq, int(max_blocks), total_q),
|
| 192 |
+
float("-inf"),
|
| 193 |
+
dtype=torch.float32,
|
| 194 |
+
device=q.device,
|
| 195 |
+
)
|
| 196 |
+
ops.msa_indexer_block_scores(
|
| 197 |
+
q.contiguous(),
|
| 198 |
+
k_pages.contiguous(),
|
| 199 |
+
batch_of_q.contiguous(),
|
| 200 |
+
cu_q.contiguous(),
|
| 201 |
+
cu_k.contiguous(),
|
| 202 |
+
cu_pages.contiguous(),
|
| 203 |
+
kv_indices.contiguous(),
|
| 204 |
+
1 if causal else 0,
|
| 205 |
+
scores,
|
| 206 |
+
)
|
| 207 |
+
return scores
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
if _HAS_NATIVE_OPS:
|
| 211 |
+
|
| 212 |
+
@torch.library.register_fake(
|
| 213 |
+
add_op_namespace_prefix("msa_nvfp4_dequant_swizzled_to_bf16")
|
| 214 |
+
)
|
| 215 |
+
def _msa_nvfp4_dequant_swizzled_to_bf16_fake(
|
| 216 |
+
packed: torch.Tensor,
|
| 217 |
+
scale_128x4: torch.Tensor,
|
| 218 |
+
global_scale: float,
|
| 219 |
+
out: torch.Tensor,
|
| 220 |
+
) -> None:
|
| 221 |
+
return None
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
def native_nvfp4_dequant_swizzled_to_bf16(
|
| 225 |
+
packed: torch.Tensor,
|
| 226 |
+
scale_128x4: torch.Tensor,
|
| 227 |
+
global_scale: torch.Tensor | float,
|
| 228 |
+
) -> torch.Tensor:
|
| 229 |
+
"""Expand swizzled NVFP4 weights/KV to dense BF16 with the native CUDA path."""
|
| 230 |
+
|
| 231 |
+
if not _HAS_NATIVE_OPS:
|
| 232 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 233 |
+
if packed.dtype is not torch.uint8:
|
| 234 |
+
raise TypeError("packed must be torch.uint8")
|
| 235 |
+
if scale_128x4.dtype is not torch.uint8:
|
| 236 |
+
raise TypeError("scale_128x4 must be torch.uint8")
|
| 237 |
+
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 238 |
+
out = torch.empty(original_shape, device=packed.device, dtype=torch.bfloat16)
|
| 239 |
+
if isinstance(global_scale, torch.Tensor):
|
| 240 |
+
global_scale_value = float(global_scale.reshape(-1)[0].item())
|
| 241 |
+
else:
|
| 242 |
+
global_scale_value = float(global_scale)
|
| 243 |
+
ops.msa_nvfp4_dequant_swizzled_to_bf16(
|
| 244 |
+
packed.contiguous(),
|
| 245 |
+
scale_128x4.contiguous(),
|
| 246 |
+
global_scale_value,
|
| 247 |
+
out,
|
| 248 |
+
)
|
| 249 |
+
return out
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
__all__ = [
|
| 253 |
+
"has_native_ops",
|
| 254 |
+
"native_topk_from_scores",
|
| 255 |
+
"native_decode_mma_supported",
|
| 256 |
+
"native_decode_sparse_attn_mma_paged",
|
| 257 |
+
"native_indexer_block_scores",
|
| 258 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 259 |
+
]
|
build/torch211-cxx11-cu128-x86_64-linux/_ops.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
import torch
|
| 2 |
-
from . import
|
| 3 |
-
ops = torch.ops.
|
| 4 |
|
| 5 |
def add_op_namespace_prefix(op_name: str):
|
| 6 |
"""
|
| 7 |
Prefix op by namespace.
|
| 8 |
"""
|
| 9 |
-
return f"
|
|
|
|
| 1 |
import torch
|
| 2 |
+
from . import _minimaxai_msa_blackwell_cuda_25b0067
|
| 3 |
+
ops = torch.ops._minimaxai_msa_blackwell_cuda_25b0067
|
| 4 |
|
| 5 |
def add_op_namespace_prefix(op_name: str):
|
| 6 |
"""
|
| 7 |
Prefix op by namespace.
|
| 8 |
"""
|
| 9 |
+
return f"_minimaxai_msa_blackwell_cuda_25b0067::{op_name}"
|
build/torch211-cxx11-cu128-x86_64-linux/api_status.py
CHANGED
|
@@ -22,6 +22,7 @@ V1_AVAILABLE_FUNCTIONS = (
|
|
| 22 |
"nvfp4_global_scale_from_amax",
|
| 23 |
"has_native_ops",
|
| 24 |
"native_topk_from_scores",
|
|
|
|
| 25 |
"flash_decode_with_topk_idx",
|
| 26 |
"flash_decode_with_gqa_share_sparse",
|
| 27 |
"naive_flash_decode_with_topk_idx",
|
|
@@ -55,7 +56,7 @@ _OFFICIAL_API_STATUS = {
|
|
| 55 |
"sparse_atten_nvfp4_kv_func": {
|
| 56 |
"status": "available",
|
| 57 |
"target": "blackwell-prefill-nvfp4",
|
| 58 |
-
"reason": "Official NVFP4 KV prefill API is available via NVFP4 dequantization followed by the Blackwell prefill wrapper.",
|
| 59 |
},
|
| 60 |
"sparse_decode_atten_func": {
|
| 61 |
"status": "available",
|
|
@@ -70,12 +71,12 @@ _OFFICIAL_API_STATUS = {
|
|
| 70 |
"fp4_indexer_block_scores": {
|
| 71 |
"status": "available",
|
| 72 |
"target": "blackwell-fp4-indexer",
|
| 73 |
-
"reason": "Official FP4 block-score API
|
| 74 |
},
|
| 75 |
"build_k2q_csr": {
|
| 76 |
"status": "available",
|
| 77 |
"target": "v1",
|
| 78 |
-
"reason": "
|
| 79 |
},
|
| 80 |
"SparseK2qCsrBuilderSm100": {
|
| 81 |
"status": "available",
|
|
|
|
| 22 |
"nvfp4_global_scale_from_amax",
|
| 23 |
"has_native_ops",
|
| 24 |
"native_topk_from_scores",
|
| 25 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 26 |
"flash_decode_with_topk_idx",
|
| 27 |
"flash_decode_with_gqa_share_sparse",
|
| 28 |
"naive_flash_decode_with_topk_idx",
|
|
|
|
| 56 |
"sparse_atten_nvfp4_kv_func": {
|
| 57 |
"status": "available",
|
| 58 |
"target": "blackwell-prefill-nvfp4",
|
| 59 |
+
"reason": "Official NVFP4 KV prefill API is available via native swizzled NVFP4 dequantization followed by the Blackwell prefill wrapper.",
|
| 60 |
},
|
| 61 |
"sparse_decode_atten_func": {
|
| 62 |
"status": "available",
|
|
|
|
| 71 |
"fp4_indexer_block_scores": {
|
| 72 |
"status": "available",
|
| 73 |
"target": "blackwell-fp4-indexer",
|
| 74 |
+
"reason": "Official FP4 block-score API uses the native Blackwell block-score kernel in built artifacts, with a reference fallback in source-tree mode.",
|
| 75 |
},
|
| 76 |
"build_k2q_csr": {
|
| 77 |
"status": "available",
|
| 78 |
"target": "v1",
|
| 79 |
+
"reason": "CSR construction helper is available for the official prefill API.",
|
| 80 |
},
|
| 81 |
"SparseK2qCsrBuilderSm100": {
|
| 82 |
"status": "available",
|
build/torch211-cxx11-cu128-x86_64-linux/decode/topk_sparse.py
CHANGED
|
@@ -8,6 +8,10 @@ import triton.language as tl
|
|
| 8 |
|
| 9 |
from .._compat import is_hip # vendored: was `from sglang.srt.utils import is_hip`
|
| 10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
from ..common.utils import robust_allocator
|
| 12 |
|
| 13 |
_is_hip = is_hip()
|
|
@@ -341,6 +345,22 @@ def flash_decode_with_gqa_share_sparse(
|
|
| 341 |
# sm scale
|
| 342 |
if sm_scale is None:
|
| 343 |
sm_scale = head_dim**-0.5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 344 |
# Pick NUM_TOPK_CHUNKS so total grid ≈ TARGET_GRID. Same constraints as
|
| 345 |
# flash_decode_with_topk_idx: must be power of 2 (Triton arange) and must
|
| 346 |
# only depend on shape constants (so grid is fixed within a cuda graph).
|
|
|
|
| 8 |
|
| 9 |
from .._compat import is_hip # vendored: was `from sglang.srt.utils import is_hip`
|
| 10 |
|
| 11 |
+
from .._native import (
|
| 12 |
+
native_decode_mma_supported,
|
| 13 |
+
native_decode_sparse_attn_mma_paged,
|
| 14 |
+
)
|
| 15 |
from ..common.utils import robust_allocator
|
| 16 |
|
| 17 |
_is_hip = is_hip()
|
|
|
|
| 345 |
# sm scale
|
| 346 |
if sm_scale is None:
|
| 347 |
sm_scale = head_dim**-0.5
|
| 348 |
+
# Fast path: native tensor-core decode for the M3 MSA shape. Falls through
|
| 349 |
+
# to the Triton kernel for other shapes, sink, or fp8 caches.
|
| 350 |
+
if sink is None and not is_fp8 and native_decode_mma_supported(
|
| 351 |
+
q, k_cache, block_size=block_size
|
| 352 |
+
):
|
| 353 |
+
return native_decode_sparse_attn_mma_paged(
|
| 354 |
+
q,
|
| 355 |
+
k_cache,
|
| 356 |
+
v_cache,
|
| 357 |
+
req_to_token,
|
| 358 |
+
seq_lens,
|
| 359 |
+
slot_ids,
|
| 360 |
+
block_size,
|
| 361 |
+
topk_idx,
|
| 362 |
+
sm_scale,
|
| 363 |
+
)
|
| 364 |
# Pick NUM_TOPK_CHUNKS so total grid ≈ TARGET_GRID. Same constraints as
|
| 365 |
# flash_decode_with_topk_idx: must be power of 2 (Triton arange) and must
|
| 366 |
# only depend on shape constants (so grid is fixed within a cuda graph).
|
build/torch211-cxx11-cu128-x86_64-linux/interface.py
CHANGED
|
@@ -7,6 +7,11 @@ from typing import Optional
|
|
| 7 |
|
| 8 |
import torch
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
from .decode.topk_sparse import flash_decode_with_gqa_share_sparse
|
| 11 |
from .prefill.topk_sparse import flash_prefill_with_gqa_share_sparse
|
| 12 |
from .quantize import Nvfp4QuantizedTensor, dequantize_nvfp4_128x4_to_bf16
|
|
@@ -488,6 +493,12 @@ def _nvfp4_dequant_kv(
|
|
| 488 |
) -> torch.Tensor:
|
| 489 |
if packed.dtype is not torch.uint8:
|
| 490 |
return packed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 491 |
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 492 |
rows = 1
|
| 493 |
for dim in original_shape[:-1]:
|
|
@@ -572,11 +583,12 @@ def fp4_indexer_block_scores(
|
|
| 572 |
qo_offset: Optional[torch.Tensor] = None,
|
| 573 |
scale_layout: str = "preordered_mma",
|
| 574 |
) -> torch.Tensor:
|
| 575 |
-
"""
|
| 576 |
|
| 577 |
Returns the official shape `[Hq, ceil(max_seqlen_k / 128), total_q]`.
|
| 578 |
-
|
| 579 |
-
|
|
|
|
| 580 |
"""
|
| 581 |
|
| 582 |
del qo_offset
|
|
@@ -599,6 +611,29 @@ def fp4_indexer_block_scores(
|
|
| 599 |
|
| 600 |
q = _apply_public_fp4_scale(_unpack_e2m1_fp4(q_fp4), q_scale)
|
| 601 |
k = _apply_public_fp4_scale(_unpack_e2m1_fp4(k_fp4), k_scale)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 602 |
gqa = hq // hkv
|
| 603 |
batch = int(cu_seqlens_q.numel()) - 1
|
| 604 |
cu_q = cu_seqlens_q.to("cpu", non_blocking=False).tolist()
|
|
|
|
| 7 |
|
| 8 |
import torch
|
| 9 |
|
| 10 |
+
from ._native import (
|
| 11 |
+
has_native_ops,
|
| 12 |
+
native_indexer_block_scores,
|
| 13 |
+
native_nvfp4_dequant_swizzled_to_bf16,
|
| 14 |
+
)
|
| 15 |
from .decode.topk_sparse import flash_decode_with_gqa_share_sparse
|
| 16 |
from .prefill.topk_sparse import flash_prefill_with_gqa_share_sparse
|
| 17 |
from .quantize import Nvfp4QuantizedTensor, dequantize_nvfp4_128x4_to_bf16
|
|
|
|
| 493 |
) -> torch.Tensor:
|
| 494 |
if packed.dtype is not torch.uint8:
|
| 495 |
return packed
|
| 496 |
+
if has_native_ops() and packed.is_cuda:
|
| 497 |
+
return native_nvfp4_dequant_swizzled_to_bf16(
|
| 498 |
+
packed,
|
| 499 |
+
scale_128x4,
|
| 500 |
+
global_scale,
|
| 501 |
+
)
|
| 502 |
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 503 |
rows = 1
|
| 504 |
for dim in original_shape[:-1]:
|
|
|
|
| 583 |
qo_offset: Optional[torch.Tensor] = None,
|
| 584 |
scale_layout: str = "preordered_mma",
|
| 585 |
) -> torch.Tensor:
|
| 586 |
+
"""FP4 block-score API for Blackwell.
|
| 587 |
|
| 588 |
Returns the official shape `[Hq, ceil(max_seqlen_k / 128), total_q]`.
|
| 589 |
+
Built artifacts route CUDA tensors through the native Blackwell block-score
|
| 590 |
+
kernel. Source-tree mode uses the reference loop below so the API remains
|
| 591 |
+
testable before the extension is built.
|
| 592 |
"""
|
| 593 |
|
| 594 |
del qo_offset
|
|
|
|
| 611 |
|
| 612 |
q = _apply_public_fp4_scale(_unpack_e2m1_fp4(q_fp4), q_scale)
|
| 613 |
k = _apply_public_fp4_scale(_unpack_e2m1_fp4(k_fp4), k_scale)
|
| 614 |
+
|
| 615 |
+
# Native block-max QK kernel for the cubic scoring loop when available.
|
| 616 |
+
# Same dequant numerics as the reference (bf16 compute); falls back to the
|
| 617 |
+
# Python reference below in source-tree mode.
|
| 618 |
+
if has_native_ops() and q_fp4.is_cuda:
|
| 619 |
+
batch = int(cu_seqlens_q.numel()) - 1
|
| 620 |
+
q_lens = (cu_seqlens_q[1:] - cu_seqlens_q[:-1]).to(torch.int64)
|
| 621 |
+
batch_of_q = torch.repeat_interleave(
|
| 622 |
+
torch.arange(batch, device=q_fp4.device, dtype=torch.int32),
|
| 623 |
+
q_lens,
|
| 624 |
+
)
|
| 625 |
+
return native_indexer_block_scores(
|
| 626 |
+
q.to(torch.bfloat16),
|
| 627 |
+
k.to(torch.bfloat16),
|
| 628 |
+
batch_of_q,
|
| 629 |
+
cu_seqlens_q.to(torch.int32),
|
| 630 |
+
cu_seqlens_k.to(torch.int32),
|
| 631 |
+
cu_page_offsets.to(torch.int32),
|
| 632 |
+
kv_indices.to(torch.int32),
|
| 633 |
+
max_blocks=max_blocks,
|
| 634 |
+
causal=causal,
|
| 635 |
+
)
|
| 636 |
+
|
| 637 |
gqa = hq // hkv
|
| 638 |
batch = int(cu_seqlens_q.numel()) - 1
|
| 639 |
cu_q = cu_seqlens_q.to("cpu", non_blocking=False).tolist()
|
build/torch211-cxx11-cu128-x86_64-linux/metadata.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"name": "minimaxai-msa-blackwell",
|
| 3 |
-
"id": "
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"python-depends": [],
|
|
@@ -13,18 +13,18 @@
|
|
| 13 |
"digest": {
|
| 14 |
"algorithm": "sha256",
|
| 15 |
"files": {
|
| 16 |
-
"__init__.py": "
|
| 17 |
"_compat.py": "5Wy4a96HVMD8omRNsGg8rQJ+0qCCeXiDANk0CuyyP0I=",
|
| 18 |
-
"
|
| 19 |
-
"_native.py": "
|
| 20 |
-
"_ops.py": "
|
| 21 |
-
"api_status.py": "
|
| 22 |
"common/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 23 |
"common/utils.py": "qtwh+wZoySlsWWALvWGVsmcIHKkdZUwePxUZ42tfWxc=",
|
| 24 |
"decode/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 25 |
"decode/flash_with_topk_idx.py": "Pk70+HJ60IKuy4KJC6hPdMtD2BjwPfSMabFiIBODWiQ=",
|
| 26 |
-
"decode/topk_sparse.py": "
|
| 27 |
-
"interface.py": "
|
| 28 |
"minimaxai_msa_blackwell/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY=",
|
| 29 |
"naive/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 30 |
"naive/flash_with_topk_idx.py": "K7WQsRdO9+H2sz7pZ6axnJwE1OmnF0egdKtftHuChig=",
|
|
|
|
| 1 |
{
|
| 2 |
"name": "minimaxai-msa-blackwell",
|
| 3 |
+
"id": "_minimaxai_msa_blackwell_cuda_25b0067",
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"python-depends": [],
|
|
|
|
| 13 |
"digest": {
|
| 14 |
"algorithm": "sha256",
|
| 15 |
"files": {
|
| 16 |
+
"__init__.py": "oPB7xQhjHd9+aLVJkEmJkZOXOwMEarmCdj3SBbhH2bM=",
|
| 17 |
"_compat.py": "5Wy4a96HVMD8omRNsGg8rQJ+0qCCeXiDANk0CuyyP0I=",
|
| 18 |
+
"_minimaxai_msa_blackwell_cuda_25b0067.abi3.so": "UoiDhzhz2aSCy+k+sOoOxb5/DqwAndixA6BgmEHAMtU=",
|
| 19 |
+
"_native.py": "wTh66DiIKxsJ5m8fkAXKSCBYD3CVFVx4PFxceQiwvPY=",
|
| 20 |
+
"_ops.py": "ikU3Lg+kgswKktYjNSq5f4DmgyTR8dnxV8lH3rmOWvk=",
|
| 21 |
+
"api_status.py": "7oZzIkb4fuwkAz3r4Q1slHbOfaP3jwVB647Ok223ATk=",
|
| 22 |
"common/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 23 |
"common/utils.py": "qtwh+wZoySlsWWALvWGVsmcIHKkdZUwePxUZ42tfWxc=",
|
| 24 |
"decode/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 25 |
"decode/flash_with_topk_idx.py": "Pk70+HJ60IKuy4KJC6hPdMtD2BjwPfSMabFiIBODWiQ=",
|
| 26 |
+
"decode/topk_sparse.py": "uINcV9SP5sAf9jYPsPvyQ9lon8sajZ8Qn/yJ+2LA8NU=",
|
| 27 |
+
"interface.py": "jfhBHGyunFF+OdFycJYyptNNIAngKrXY67buTXAN66M=",
|
| 28 |
"minimaxai_msa_blackwell/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY=",
|
| 29 |
"naive/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 30 |
"naive/flash_with_topk_idx.py": "K7WQsRdO9+H2sz7pZ6axnJwE1OmnF0egdKtftHuChig=",
|
build/torch211-cxx11-cu130-x86_64-linux/__init__.py
CHANGED
|
@@ -7,9 +7,12 @@ MiniMax-M3 decode-sparse attention path used by FlashRT's MiniMax Spark runtime.
|
|
| 7 |
|
| 8 |
Implementation status:
|
| 9 |
* native CUDA helper: score -> top-k sparse block ids;
|
| 10 |
-
*
|
|
|
|
|
|
|
|
|
|
| 11 |
* MiniMaxAI/msa compatibility wrappers for CSR prefill, decode, NVFP4 helpers,
|
| 12 |
-
and FP4 block-score
|
| 13 |
|
| 14 |
The upstream MiniMaxAI/msa package is SM100-only; this package is the Blackwell
|
| 15 |
extension path. The public API is Tensor-oriented and independent from
|
|
@@ -48,7 +51,11 @@ from .interface import (
|
|
| 48 |
sparse_atten_nvfp4_kv_func,
|
| 49 |
sparse_decode_atten_func,
|
| 50 |
)
|
| 51 |
-
from ._native import
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
from .naive.flash_with_topk_idx import naive_flash_decode_with_topk_idx
|
| 53 |
from .naive.topk_sparse import naive_flash_decode_with_gqa_share_sparse
|
| 54 |
from .quantize import (
|
|
@@ -88,6 +95,7 @@ __all__ = [
|
|
| 88 |
"flash_decode_with_gqa_share_sparse",
|
| 89 |
"has_native_ops",
|
| 90 |
"native_topk_from_scores",
|
|
|
|
| 91 |
"naive_flash_decode_with_gqa_share_sparse",
|
| 92 |
"naive_flash_decode_with_topk_idx",
|
| 93 |
"get_cu_seqblocks",
|
|
|
|
| 7 |
|
| 8 |
Implementation status:
|
| 9 |
* native CUDA helper: score -> top-k sparse block ids;
|
| 10 |
+
* native CUDA tensor-core sparse decode for the MiniMax-M3 Blackwell shape;
|
| 11 |
+
* native CUDA FP4 block-score indexer;
|
| 12 |
+
* native CUDA helper: swizzled NVFP4 -> BF16 dequant for the W4A16 quality path;
|
| 13 |
+
* Blackwell-validated sparse prefill path;
|
| 14 |
* MiniMaxAI/msa compatibility wrappers for CSR prefill, decode, NVFP4 helpers,
|
| 15 |
+
and FP4 block-score helpers.
|
| 16 |
|
| 17 |
The upstream MiniMaxAI/msa package is SM100-only; this package is the Blackwell
|
| 18 |
extension path. The public API is Tensor-oriented and independent from
|
|
|
|
| 51 |
sparse_atten_nvfp4_kv_func,
|
| 52 |
sparse_decode_atten_func,
|
| 53 |
)
|
| 54 |
+
from ._native import (
|
| 55 |
+
has_native_ops,
|
| 56 |
+
native_nvfp4_dequant_swizzled_to_bf16,
|
| 57 |
+
native_topk_from_scores,
|
| 58 |
+
)
|
| 59 |
from .naive.flash_with_topk_idx import naive_flash_decode_with_topk_idx
|
| 60 |
from .naive.topk_sparse import naive_flash_decode_with_gqa_share_sparse
|
| 61 |
from .quantize import (
|
|
|
|
| 95 |
"flash_decode_with_gqa_share_sparse",
|
| 96 |
"has_native_ops",
|
| 97 |
"native_topk_from_scores",
|
| 98 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 99 |
"naive_flash_decode_with_gqa_share_sparse",
|
| 100 |
"naive_flash_decode_with_topk_idx",
|
| 101 |
"get_cu_seqblocks",
|
build/torch211-cxx11-cu130-x86_64-linux/{_minimaxai_msa_blackwell_cuda_58018d1.abi3.so → _minimaxai_msa_blackwell_cuda_25b0067.abi3.so}
RENAMED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a053c1fd69c4df3f94e566a7c4d88ba943f8d5cece714ade52789f6819a961ac
|
| 3 |
+
size 729824
|
build/torch211-cxx11-cu130-x86_64-linux/_native.py
CHANGED
|
@@ -62,4 +62,198 @@ def native_topk_from_scores(
|
|
| 62 |
return out
|
| 63 |
|
| 64 |
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
return out
|
| 63 |
|
| 64 |
|
| 65 |
+
if _HAS_NATIVE_OPS:
|
| 66 |
+
|
| 67 |
+
@torch.library.register_fake(
|
| 68 |
+
add_op_namespace_prefix("msa_decode_sparse_attn_mma_paged")
|
| 69 |
+
)
|
| 70 |
+
def _msa_decode_sparse_attn_mma_paged_fake(
|
| 71 |
+
q: torch.Tensor,
|
| 72 |
+
k_cache: torch.Tensor,
|
| 73 |
+
v_cache: torch.Tensor,
|
| 74 |
+
req_to_token: torch.Tensor,
|
| 75 |
+
seq_lens: torch.Tensor,
|
| 76 |
+
slot_ids: torch.Tensor,
|
| 77 |
+
topk_idx: torch.Tensor,
|
| 78 |
+
block_size: int,
|
| 79 |
+
sm_scale: float,
|
| 80 |
+
out: torch.Tensor,
|
| 81 |
+
) -> None:
|
| 82 |
+
return None
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def native_decode_mma_supported(
|
| 86 |
+
q: torch.Tensor,
|
| 87 |
+
k_cache: torch.Tensor,
|
| 88 |
+
*,
|
| 89 |
+
block_size: int,
|
| 90 |
+
) -> bool:
|
| 91 |
+
"""Whether the tensor-core decode kernel applies to these inputs.
|
| 92 |
+
|
| 93 |
+
The mma kernel is specialized for the M3 MSA shape: head_dim 128, GQA
|
| 94 |
+
group (Hq/Hkv) 16, bf16, and a block size that is a multiple of 64.
|
| 95 |
+
"""
|
| 96 |
+
|
| 97 |
+
if not _HAS_NATIVE_OPS:
|
| 98 |
+
return False
|
| 99 |
+
if q.dtype is not torch.bfloat16 or k_cache.dtype is not torch.bfloat16:
|
| 100 |
+
return False
|
| 101 |
+
if q.dim() != 3 or k_cache.dim() != 3:
|
| 102 |
+
return False
|
| 103 |
+
head_dim = int(q.shape[-1])
|
| 104 |
+
num_q_heads = int(q.shape[1])
|
| 105 |
+
num_kv_heads = int(k_cache.shape[1])
|
| 106 |
+
if head_dim != 128 or num_kv_heads <= 0:
|
| 107 |
+
return False
|
| 108 |
+
if num_q_heads % num_kv_heads != 0 or num_q_heads // num_kv_heads != 16:
|
| 109 |
+
return False
|
| 110 |
+
if int(block_size) % 64 != 0:
|
| 111 |
+
return False
|
| 112 |
+
return True
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def native_decode_sparse_attn_mma_paged(
|
| 116 |
+
q: torch.Tensor,
|
| 117 |
+
k_cache: torch.Tensor,
|
| 118 |
+
v_cache: torch.Tensor,
|
| 119 |
+
req_to_token: torch.Tensor,
|
| 120 |
+
seq_lens: torch.Tensor,
|
| 121 |
+
slot_ids: torch.Tensor,
|
| 122 |
+
block_size: int,
|
| 123 |
+
topk_idx: torch.Tensor,
|
| 124 |
+
sm_scale: float,
|
| 125 |
+
) -> torch.Tensor:
|
| 126 |
+
"""Paged tensor-core block-sparse GQA decode. Returns [B, Hq, D] bf16."""
|
| 127 |
+
|
| 128 |
+
if not _HAS_NATIVE_OPS:
|
| 129 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 130 |
+
out = torch.empty(
|
| 131 |
+
(int(q.shape[0]), int(q.shape[1]), int(q.shape[2])),
|
| 132 |
+
device=q.device,
|
| 133 |
+
dtype=q.dtype,
|
| 134 |
+
)
|
| 135 |
+
ops.msa_decode_sparse_attn_mma_paged(
|
| 136 |
+
q.contiguous(),
|
| 137 |
+
k_cache.contiguous(),
|
| 138 |
+
v_cache.contiguous(),
|
| 139 |
+
req_to_token.contiguous(),
|
| 140 |
+
seq_lens.contiguous(),
|
| 141 |
+
slot_ids.contiguous(),
|
| 142 |
+
topk_idx.contiguous(),
|
| 143 |
+
int(block_size),
|
| 144 |
+
float(sm_scale),
|
| 145 |
+
out,
|
| 146 |
+
)
|
| 147 |
+
return out
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
if _HAS_NATIVE_OPS:
|
| 151 |
+
|
| 152 |
+
@torch.library.register_fake(
|
| 153 |
+
add_op_namespace_prefix("msa_indexer_block_scores")
|
| 154 |
+
)
|
| 155 |
+
def _msa_indexer_block_scores_fake(
|
| 156 |
+
q: torch.Tensor,
|
| 157 |
+
k_pages: torch.Tensor,
|
| 158 |
+
batch_of_q: torch.Tensor,
|
| 159 |
+
cu_q: torch.Tensor,
|
| 160 |
+
cu_k: torch.Tensor,
|
| 161 |
+
cu_pages: torch.Tensor,
|
| 162 |
+
kv_indices: torch.Tensor,
|
| 163 |
+
causal: int,
|
| 164 |
+
scores: torch.Tensor,
|
| 165 |
+
) -> None:
|
| 166 |
+
return None
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
def native_indexer_block_scores(
|
| 170 |
+
q: torch.Tensor,
|
| 171 |
+
k_pages: torch.Tensor,
|
| 172 |
+
batch_of_q: torch.Tensor,
|
| 173 |
+
cu_q: torch.Tensor,
|
| 174 |
+
cu_k: torch.Tensor,
|
| 175 |
+
cu_pages: torch.Tensor,
|
| 176 |
+
kv_indices: torch.Tensor,
|
| 177 |
+
*,
|
| 178 |
+
max_blocks: int,
|
| 179 |
+
causal: bool,
|
| 180 |
+
) -> torch.Tensor:
|
| 181 |
+
"""Block-max QK indexer scores. q/k_pages are bf16 (already dequantized).
|
| 182 |
+
|
| 183 |
+
Returns [Hq, max_blocks, total_q] f32 (-inf where no key is visible).
|
| 184 |
+
"""
|
| 185 |
+
|
| 186 |
+
if not _HAS_NATIVE_OPS:
|
| 187 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 188 |
+
total_q = int(q.shape[0])
|
| 189 |
+
hq = int(q.shape[1])
|
| 190 |
+
scores = torch.full(
|
| 191 |
+
(hq, int(max_blocks), total_q),
|
| 192 |
+
float("-inf"),
|
| 193 |
+
dtype=torch.float32,
|
| 194 |
+
device=q.device,
|
| 195 |
+
)
|
| 196 |
+
ops.msa_indexer_block_scores(
|
| 197 |
+
q.contiguous(),
|
| 198 |
+
k_pages.contiguous(),
|
| 199 |
+
batch_of_q.contiguous(),
|
| 200 |
+
cu_q.contiguous(),
|
| 201 |
+
cu_k.contiguous(),
|
| 202 |
+
cu_pages.contiguous(),
|
| 203 |
+
kv_indices.contiguous(),
|
| 204 |
+
1 if causal else 0,
|
| 205 |
+
scores,
|
| 206 |
+
)
|
| 207 |
+
return scores
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
if _HAS_NATIVE_OPS:
|
| 211 |
+
|
| 212 |
+
@torch.library.register_fake(
|
| 213 |
+
add_op_namespace_prefix("msa_nvfp4_dequant_swizzled_to_bf16")
|
| 214 |
+
)
|
| 215 |
+
def _msa_nvfp4_dequant_swizzled_to_bf16_fake(
|
| 216 |
+
packed: torch.Tensor,
|
| 217 |
+
scale_128x4: torch.Tensor,
|
| 218 |
+
global_scale: float,
|
| 219 |
+
out: torch.Tensor,
|
| 220 |
+
) -> None:
|
| 221 |
+
return None
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
def native_nvfp4_dequant_swizzled_to_bf16(
|
| 225 |
+
packed: torch.Tensor,
|
| 226 |
+
scale_128x4: torch.Tensor,
|
| 227 |
+
global_scale: torch.Tensor | float,
|
| 228 |
+
) -> torch.Tensor:
|
| 229 |
+
"""Expand swizzled NVFP4 weights/KV to dense BF16 with the native CUDA path."""
|
| 230 |
+
|
| 231 |
+
if not _HAS_NATIVE_OPS:
|
| 232 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 233 |
+
if packed.dtype is not torch.uint8:
|
| 234 |
+
raise TypeError("packed must be torch.uint8")
|
| 235 |
+
if scale_128x4.dtype is not torch.uint8:
|
| 236 |
+
raise TypeError("scale_128x4 must be torch.uint8")
|
| 237 |
+
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 238 |
+
out = torch.empty(original_shape, device=packed.device, dtype=torch.bfloat16)
|
| 239 |
+
if isinstance(global_scale, torch.Tensor):
|
| 240 |
+
global_scale_value = float(global_scale.reshape(-1)[0].item())
|
| 241 |
+
else:
|
| 242 |
+
global_scale_value = float(global_scale)
|
| 243 |
+
ops.msa_nvfp4_dequant_swizzled_to_bf16(
|
| 244 |
+
packed.contiguous(),
|
| 245 |
+
scale_128x4.contiguous(),
|
| 246 |
+
global_scale_value,
|
| 247 |
+
out,
|
| 248 |
+
)
|
| 249 |
+
return out
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
__all__ = [
|
| 253 |
+
"has_native_ops",
|
| 254 |
+
"native_topk_from_scores",
|
| 255 |
+
"native_decode_mma_supported",
|
| 256 |
+
"native_decode_sparse_attn_mma_paged",
|
| 257 |
+
"native_indexer_block_scores",
|
| 258 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 259 |
+
]
|
build/torch211-cxx11-cu130-x86_64-linux/_ops.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
import torch
|
| 2 |
-
from . import
|
| 3 |
-
ops = torch.ops.
|
| 4 |
|
| 5 |
def add_op_namespace_prefix(op_name: str):
|
| 6 |
"""
|
| 7 |
Prefix op by namespace.
|
| 8 |
"""
|
| 9 |
-
return f"
|
|
|
|
| 1 |
import torch
|
| 2 |
+
from . import _minimaxai_msa_blackwell_cuda_25b0067
|
| 3 |
+
ops = torch.ops._minimaxai_msa_blackwell_cuda_25b0067
|
| 4 |
|
| 5 |
def add_op_namespace_prefix(op_name: str):
|
| 6 |
"""
|
| 7 |
Prefix op by namespace.
|
| 8 |
"""
|
| 9 |
+
return f"_minimaxai_msa_blackwell_cuda_25b0067::{op_name}"
|
build/torch211-cxx11-cu130-x86_64-linux/api_status.py
CHANGED
|
@@ -22,6 +22,7 @@ V1_AVAILABLE_FUNCTIONS = (
|
|
| 22 |
"nvfp4_global_scale_from_amax",
|
| 23 |
"has_native_ops",
|
| 24 |
"native_topk_from_scores",
|
|
|
|
| 25 |
"flash_decode_with_topk_idx",
|
| 26 |
"flash_decode_with_gqa_share_sparse",
|
| 27 |
"naive_flash_decode_with_topk_idx",
|
|
@@ -55,7 +56,7 @@ _OFFICIAL_API_STATUS = {
|
|
| 55 |
"sparse_atten_nvfp4_kv_func": {
|
| 56 |
"status": "available",
|
| 57 |
"target": "blackwell-prefill-nvfp4",
|
| 58 |
-
"reason": "Official NVFP4 KV prefill API is available via NVFP4 dequantization followed by the Blackwell prefill wrapper.",
|
| 59 |
},
|
| 60 |
"sparse_decode_atten_func": {
|
| 61 |
"status": "available",
|
|
@@ -70,12 +71,12 @@ _OFFICIAL_API_STATUS = {
|
|
| 70 |
"fp4_indexer_block_scores": {
|
| 71 |
"status": "available",
|
| 72 |
"target": "blackwell-fp4-indexer",
|
| 73 |
-
"reason": "Official FP4 block-score API
|
| 74 |
},
|
| 75 |
"build_k2q_csr": {
|
| 76 |
"status": "available",
|
| 77 |
"target": "v1",
|
| 78 |
-
"reason": "
|
| 79 |
},
|
| 80 |
"SparseK2qCsrBuilderSm100": {
|
| 81 |
"status": "available",
|
|
|
|
| 22 |
"nvfp4_global_scale_from_amax",
|
| 23 |
"has_native_ops",
|
| 24 |
"native_topk_from_scores",
|
| 25 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 26 |
"flash_decode_with_topk_idx",
|
| 27 |
"flash_decode_with_gqa_share_sparse",
|
| 28 |
"naive_flash_decode_with_topk_idx",
|
|
|
|
| 56 |
"sparse_atten_nvfp4_kv_func": {
|
| 57 |
"status": "available",
|
| 58 |
"target": "blackwell-prefill-nvfp4",
|
| 59 |
+
"reason": "Official NVFP4 KV prefill API is available via native swizzled NVFP4 dequantization followed by the Blackwell prefill wrapper.",
|
| 60 |
},
|
| 61 |
"sparse_decode_atten_func": {
|
| 62 |
"status": "available",
|
|
|
|
| 71 |
"fp4_indexer_block_scores": {
|
| 72 |
"status": "available",
|
| 73 |
"target": "blackwell-fp4-indexer",
|
| 74 |
+
"reason": "Official FP4 block-score API uses the native Blackwell block-score kernel in built artifacts, with a reference fallback in source-tree mode.",
|
| 75 |
},
|
| 76 |
"build_k2q_csr": {
|
| 77 |
"status": "available",
|
| 78 |
"target": "v1",
|
| 79 |
+
"reason": "CSR construction helper is available for the official prefill API.",
|
| 80 |
},
|
| 81 |
"SparseK2qCsrBuilderSm100": {
|
| 82 |
"status": "available",
|
build/torch211-cxx11-cu130-x86_64-linux/decode/topk_sparse.py
CHANGED
|
@@ -8,6 +8,10 @@ import triton.language as tl
|
|
| 8 |
|
| 9 |
from .._compat import is_hip # vendored: was `from sglang.srt.utils import is_hip`
|
| 10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
from ..common.utils import robust_allocator
|
| 12 |
|
| 13 |
_is_hip = is_hip()
|
|
@@ -341,6 +345,22 @@ def flash_decode_with_gqa_share_sparse(
|
|
| 341 |
# sm scale
|
| 342 |
if sm_scale is None:
|
| 343 |
sm_scale = head_dim**-0.5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 344 |
# Pick NUM_TOPK_CHUNKS so total grid ≈ TARGET_GRID. Same constraints as
|
| 345 |
# flash_decode_with_topk_idx: must be power of 2 (Triton arange) and must
|
| 346 |
# only depend on shape constants (so grid is fixed within a cuda graph).
|
|
|
|
| 8 |
|
| 9 |
from .._compat import is_hip # vendored: was `from sglang.srt.utils import is_hip`
|
| 10 |
|
| 11 |
+
from .._native import (
|
| 12 |
+
native_decode_mma_supported,
|
| 13 |
+
native_decode_sparse_attn_mma_paged,
|
| 14 |
+
)
|
| 15 |
from ..common.utils import robust_allocator
|
| 16 |
|
| 17 |
_is_hip = is_hip()
|
|
|
|
| 345 |
# sm scale
|
| 346 |
if sm_scale is None:
|
| 347 |
sm_scale = head_dim**-0.5
|
| 348 |
+
# Fast path: native tensor-core decode for the M3 MSA shape. Falls through
|
| 349 |
+
# to the Triton kernel for other shapes, sink, or fp8 caches.
|
| 350 |
+
if sink is None and not is_fp8 and native_decode_mma_supported(
|
| 351 |
+
q, k_cache, block_size=block_size
|
| 352 |
+
):
|
| 353 |
+
return native_decode_sparse_attn_mma_paged(
|
| 354 |
+
q,
|
| 355 |
+
k_cache,
|
| 356 |
+
v_cache,
|
| 357 |
+
req_to_token,
|
| 358 |
+
seq_lens,
|
| 359 |
+
slot_ids,
|
| 360 |
+
block_size,
|
| 361 |
+
topk_idx,
|
| 362 |
+
sm_scale,
|
| 363 |
+
)
|
| 364 |
# Pick NUM_TOPK_CHUNKS so total grid ≈ TARGET_GRID. Same constraints as
|
| 365 |
# flash_decode_with_topk_idx: must be power of 2 (Triton arange) and must
|
| 366 |
# only depend on shape constants (so grid is fixed within a cuda graph).
|
build/torch211-cxx11-cu130-x86_64-linux/interface.py
CHANGED
|
@@ -7,6 +7,11 @@ from typing import Optional
|
|
| 7 |
|
| 8 |
import torch
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
from .decode.topk_sparse import flash_decode_with_gqa_share_sparse
|
| 11 |
from .prefill.topk_sparse import flash_prefill_with_gqa_share_sparse
|
| 12 |
from .quantize import Nvfp4QuantizedTensor, dequantize_nvfp4_128x4_to_bf16
|
|
@@ -488,6 +493,12 @@ def _nvfp4_dequant_kv(
|
|
| 488 |
) -> torch.Tensor:
|
| 489 |
if packed.dtype is not torch.uint8:
|
| 490 |
return packed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 491 |
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 492 |
rows = 1
|
| 493 |
for dim in original_shape[:-1]:
|
|
@@ -572,11 +583,12 @@ def fp4_indexer_block_scores(
|
|
| 572 |
qo_offset: Optional[torch.Tensor] = None,
|
| 573 |
scale_layout: str = "preordered_mma",
|
| 574 |
) -> torch.Tensor:
|
| 575 |
-
"""
|
| 576 |
|
| 577 |
Returns the official shape `[Hq, ceil(max_seqlen_k / 128), total_q]`.
|
| 578 |
-
|
| 579 |
-
|
|
|
|
| 580 |
"""
|
| 581 |
|
| 582 |
del qo_offset
|
|
@@ -599,6 +611,29 @@ def fp4_indexer_block_scores(
|
|
| 599 |
|
| 600 |
q = _apply_public_fp4_scale(_unpack_e2m1_fp4(q_fp4), q_scale)
|
| 601 |
k = _apply_public_fp4_scale(_unpack_e2m1_fp4(k_fp4), k_scale)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 602 |
gqa = hq // hkv
|
| 603 |
batch = int(cu_seqlens_q.numel()) - 1
|
| 604 |
cu_q = cu_seqlens_q.to("cpu", non_blocking=False).tolist()
|
|
|
|
| 7 |
|
| 8 |
import torch
|
| 9 |
|
| 10 |
+
from ._native import (
|
| 11 |
+
has_native_ops,
|
| 12 |
+
native_indexer_block_scores,
|
| 13 |
+
native_nvfp4_dequant_swizzled_to_bf16,
|
| 14 |
+
)
|
| 15 |
from .decode.topk_sparse import flash_decode_with_gqa_share_sparse
|
| 16 |
from .prefill.topk_sparse import flash_prefill_with_gqa_share_sparse
|
| 17 |
from .quantize import Nvfp4QuantizedTensor, dequantize_nvfp4_128x4_to_bf16
|
|
|
|
| 493 |
) -> torch.Tensor:
|
| 494 |
if packed.dtype is not torch.uint8:
|
| 495 |
return packed
|
| 496 |
+
if has_native_ops() and packed.is_cuda:
|
| 497 |
+
return native_nvfp4_dequant_swizzled_to_bf16(
|
| 498 |
+
packed,
|
| 499 |
+
scale_128x4,
|
| 500 |
+
global_scale,
|
| 501 |
+
)
|
| 502 |
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 503 |
rows = 1
|
| 504 |
for dim in original_shape[:-1]:
|
|
|
|
| 583 |
qo_offset: Optional[torch.Tensor] = None,
|
| 584 |
scale_layout: str = "preordered_mma",
|
| 585 |
) -> torch.Tensor:
|
| 586 |
+
"""FP4 block-score API for Blackwell.
|
| 587 |
|
| 588 |
Returns the official shape `[Hq, ceil(max_seqlen_k / 128), total_q]`.
|
| 589 |
+
Built artifacts route CUDA tensors through the native Blackwell block-score
|
| 590 |
+
kernel. Source-tree mode uses the reference loop below so the API remains
|
| 591 |
+
testable before the extension is built.
|
| 592 |
"""
|
| 593 |
|
| 594 |
del qo_offset
|
|
|
|
| 611 |
|
| 612 |
q = _apply_public_fp4_scale(_unpack_e2m1_fp4(q_fp4), q_scale)
|
| 613 |
k = _apply_public_fp4_scale(_unpack_e2m1_fp4(k_fp4), k_scale)
|
| 614 |
+
|
| 615 |
+
# Native block-max QK kernel for the cubic scoring loop when available.
|
| 616 |
+
# Same dequant numerics as the reference (bf16 compute); falls back to the
|
| 617 |
+
# Python reference below in source-tree mode.
|
| 618 |
+
if has_native_ops() and q_fp4.is_cuda:
|
| 619 |
+
batch = int(cu_seqlens_q.numel()) - 1
|
| 620 |
+
q_lens = (cu_seqlens_q[1:] - cu_seqlens_q[:-1]).to(torch.int64)
|
| 621 |
+
batch_of_q = torch.repeat_interleave(
|
| 622 |
+
torch.arange(batch, device=q_fp4.device, dtype=torch.int32),
|
| 623 |
+
q_lens,
|
| 624 |
+
)
|
| 625 |
+
return native_indexer_block_scores(
|
| 626 |
+
q.to(torch.bfloat16),
|
| 627 |
+
k.to(torch.bfloat16),
|
| 628 |
+
batch_of_q,
|
| 629 |
+
cu_seqlens_q.to(torch.int32),
|
| 630 |
+
cu_seqlens_k.to(torch.int32),
|
| 631 |
+
cu_page_offsets.to(torch.int32),
|
| 632 |
+
kv_indices.to(torch.int32),
|
| 633 |
+
max_blocks=max_blocks,
|
| 634 |
+
causal=causal,
|
| 635 |
+
)
|
| 636 |
+
|
| 637 |
gqa = hq // hkv
|
| 638 |
batch = int(cu_seqlens_q.numel()) - 1
|
| 639 |
cu_q = cu_seqlens_q.to("cpu", non_blocking=False).tolist()
|
build/torch211-cxx11-cu130-x86_64-linux/metadata.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"name": "minimaxai-msa-blackwell",
|
| 3 |
-
"id": "
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"python-depends": [],
|
|
@@ -14,18 +14,18 @@
|
|
| 14 |
"digest": {
|
| 15 |
"algorithm": "sha256",
|
| 16 |
"files": {
|
| 17 |
-
"__init__.py": "
|
| 18 |
"_compat.py": "5Wy4a96HVMD8omRNsGg8rQJ+0qCCeXiDANk0CuyyP0I=",
|
| 19 |
-
"
|
| 20 |
-
"_native.py": "
|
| 21 |
-
"_ops.py": "
|
| 22 |
-
"api_status.py": "
|
| 23 |
"common/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 24 |
"common/utils.py": "qtwh+wZoySlsWWALvWGVsmcIHKkdZUwePxUZ42tfWxc=",
|
| 25 |
"decode/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 26 |
"decode/flash_with_topk_idx.py": "Pk70+HJ60IKuy4KJC6hPdMtD2BjwPfSMabFiIBODWiQ=",
|
| 27 |
-
"decode/topk_sparse.py": "
|
| 28 |
-
"interface.py": "
|
| 29 |
"minimaxai_msa_blackwell/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY=",
|
| 30 |
"naive/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 31 |
"naive/flash_with_topk_idx.py": "K7WQsRdO9+H2sz7pZ6axnJwE1OmnF0egdKtftHuChig=",
|
|
|
|
| 1 |
{
|
| 2 |
"name": "minimaxai-msa-blackwell",
|
| 3 |
+
"id": "_minimaxai_msa_blackwell_cuda_25b0067",
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"python-depends": [],
|
|
|
|
| 14 |
"digest": {
|
| 15 |
"algorithm": "sha256",
|
| 16 |
"files": {
|
| 17 |
+
"__init__.py": "oPB7xQhjHd9+aLVJkEmJkZOXOwMEarmCdj3SBbhH2bM=",
|
| 18 |
"_compat.py": "5Wy4a96HVMD8omRNsGg8rQJ+0qCCeXiDANk0CuyyP0I=",
|
| 19 |
+
"_minimaxai_msa_blackwell_cuda_25b0067.abi3.so": "oFPB/WnE3z+U5WanxNiLqUP41c7OcUreUnifaBmpYaw=",
|
| 20 |
+
"_native.py": "wTh66DiIKxsJ5m8fkAXKSCBYD3CVFVx4PFxceQiwvPY=",
|
| 21 |
+
"_ops.py": "ikU3Lg+kgswKktYjNSq5f4DmgyTR8dnxV8lH3rmOWvk=",
|
| 22 |
+
"api_status.py": "7oZzIkb4fuwkAz3r4Q1slHbOfaP3jwVB647Ok223ATk=",
|
| 23 |
"common/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 24 |
"common/utils.py": "qtwh+wZoySlsWWALvWGVsmcIHKkdZUwePxUZ42tfWxc=",
|
| 25 |
"decode/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 26 |
"decode/flash_with_topk_idx.py": "Pk70+HJ60IKuy4KJC6hPdMtD2BjwPfSMabFiIBODWiQ=",
|
| 27 |
+
"decode/topk_sparse.py": "uINcV9SP5sAf9jYPsPvyQ9lon8sajZ8Qn/yJ+2LA8NU=",
|
| 28 |
+
"interface.py": "jfhBHGyunFF+OdFycJYyptNNIAngKrXY67buTXAN66M=",
|
| 29 |
"minimaxai_msa_blackwell/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY=",
|
| 30 |
"naive/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 31 |
"naive/flash_with_topk_idx.py": "K7WQsRdO9+H2sz7pZ6axnJwE1OmnF0egdKtftHuChig=",
|
build/torch212-cxx11-cu130-x86_64-linux/__init__.py
CHANGED
|
@@ -7,9 +7,12 @@ MiniMax-M3 decode-sparse attention path used by FlashRT's MiniMax Spark runtime.
|
|
| 7 |
|
| 8 |
Implementation status:
|
| 9 |
* native CUDA helper: score -> top-k sparse block ids;
|
| 10 |
-
*
|
|
|
|
|
|
|
|
|
|
| 11 |
* MiniMaxAI/msa compatibility wrappers for CSR prefill, decode, NVFP4 helpers,
|
| 12 |
-
and FP4 block-score
|
| 13 |
|
| 14 |
The upstream MiniMaxAI/msa package is SM100-only; this package is the Blackwell
|
| 15 |
extension path. The public API is Tensor-oriented and independent from
|
|
@@ -48,7 +51,11 @@ from .interface import (
|
|
| 48 |
sparse_atten_nvfp4_kv_func,
|
| 49 |
sparse_decode_atten_func,
|
| 50 |
)
|
| 51 |
-
from ._native import
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
from .naive.flash_with_topk_idx import naive_flash_decode_with_topk_idx
|
| 53 |
from .naive.topk_sparse import naive_flash_decode_with_gqa_share_sparse
|
| 54 |
from .quantize import (
|
|
@@ -88,6 +95,7 @@ __all__ = [
|
|
| 88 |
"flash_decode_with_gqa_share_sparse",
|
| 89 |
"has_native_ops",
|
| 90 |
"native_topk_from_scores",
|
|
|
|
| 91 |
"naive_flash_decode_with_gqa_share_sparse",
|
| 92 |
"naive_flash_decode_with_topk_idx",
|
| 93 |
"get_cu_seqblocks",
|
|
|
|
| 7 |
|
| 8 |
Implementation status:
|
| 9 |
* native CUDA helper: score -> top-k sparse block ids;
|
| 10 |
+
* native CUDA tensor-core sparse decode for the MiniMax-M3 Blackwell shape;
|
| 11 |
+
* native CUDA FP4 block-score indexer;
|
| 12 |
+
* native CUDA helper: swizzled NVFP4 -> BF16 dequant for the W4A16 quality path;
|
| 13 |
+
* Blackwell-validated sparse prefill path;
|
| 14 |
* MiniMaxAI/msa compatibility wrappers for CSR prefill, decode, NVFP4 helpers,
|
| 15 |
+
and FP4 block-score helpers.
|
| 16 |
|
| 17 |
The upstream MiniMaxAI/msa package is SM100-only; this package is the Blackwell
|
| 18 |
extension path. The public API is Tensor-oriented and independent from
|
|
|
|
| 51 |
sparse_atten_nvfp4_kv_func,
|
| 52 |
sparse_decode_atten_func,
|
| 53 |
)
|
| 54 |
+
from ._native import (
|
| 55 |
+
has_native_ops,
|
| 56 |
+
native_nvfp4_dequant_swizzled_to_bf16,
|
| 57 |
+
native_topk_from_scores,
|
| 58 |
+
)
|
| 59 |
from .naive.flash_with_topk_idx import naive_flash_decode_with_topk_idx
|
| 60 |
from .naive.topk_sparse import naive_flash_decode_with_gqa_share_sparse
|
| 61 |
from .quantize import (
|
|
|
|
| 95 |
"flash_decode_with_gqa_share_sparse",
|
| 96 |
"has_native_ops",
|
| 97 |
"native_topk_from_scores",
|
| 98 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 99 |
"naive_flash_decode_with_gqa_share_sparse",
|
| 100 |
"naive_flash_decode_with_topk_idx",
|
| 101 |
"get_cu_seqblocks",
|
build/torch212-cxx11-cu130-x86_64-linux/{_minimaxai_msa_blackwell_cuda_58018d1.abi3.so → _minimaxai_msa_blackwell_cuda_25b0067.abi3.so}
RENAMED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2ea862050a19dcc4b0c7cbfd3b519112f1b4e054cfc182a14f92876b4ae5b9f7
|
| 3 |
+
size 735888
|
build/torch212-cxx11-cu130-x86_64-linux/_native.py
CHANGED
|
@@ -62,4 +62,198 @@ def native_topk_from_scores(
|
|
| 62 |
return out
|
| 63 |
|
| 64 |
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
return out
|
| 63 |
|
| 64 |
|
| 65 |
+
if _HAS_NATIVE_OPS:
|
| 66 |
+
|
| 67 |
+
@torch.library.register_fake(
|
| 68 |
+
add_op_namespace_prefix("msa_decode_sparse_attn_mma_paged")
|
| 69 |
+
)
|
| 70 |
+
def _msa_decode_sparse_attn_mma_paged_fake(
|
| 71 |
+
q: torch.Tensor,
|
| 72 |
+
k_cache: torch.Tensor,
|
| 73 |
+
v_cache: torch.Tensor,
|
| 74 |
+
req_to_token: torch.Tensor,
|
| 75 |
+
seq_lens: torch.Tensor,
|
| 76 |
+
slot_ids: torch.Tensor,
|
| 77 |
+
topk_idx: torch.Tensor,
|
| 78 |
+
block_size: int,
|
| 79 |
+
sm_scale: float,
|
| 80 |
+
out: torch.Tensor,
|
| 81 |
+
) -> None:
|
| 82 |
+
return None
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def native_decode_mma_supported(
|
| 86 |
+
q: torch.Tensor,
|
| 87 |
+
k_cache: torch.Tensor,
|
| 88 |
+
*,
|
| 89 |
+
block_size: int,
|
| 90 |
+
) -> bool:
|
| 91 |
+
"""Whether the tensor-core decode kernel applies to these inputs.
|
| 92 |
+
|
| 93 |
+
The mma kernel is specialized for the M3 MSA shape: head_dim 128, GQA
|
| 94 |
+
group (Hq/Hkv) 16, bf16, and a block size that is a multiple of 64.
|
| 95 |
+
"""
|
| 96 |
+
|
| 97 |
+
if not _HAS_NATIVE_OPS:
|
| 98 |
+
return False
|
| 99 |
+
if q.dtype is not torch.bfloat16 or k_cache.dtype is not torch.bfloat16:
|
| 100 |
+
return False
|
| 101 |
+
if q.dim() != 3 or k_cache.dim() != 3:
|
| 102 |
+
return False
|
| 103 |
+
head_dim = int(q.shape[-1])
|
| 104 |
+
num_q_heads = int(q.shape[1])
|
| 105 |
+
num_kv_heads = int(k_cache.shape[1])
|
| 106 |
+
if head_dim != 128 or num_kv_heads <= 0:
|
| 107 |
+
return False
|
| 108 |
+
if num_q_heads % num_kv_heads != 0 or num_q_heads // num_kv_heads != 16:
|
| 109 |
+
return False
|
| 110 |
+
if int(block_size) % 64 != 0:
|
| 111 |
+
return False
|
| 112 |
+
return True
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def native_decode_sparse_attn_mma_paged(
|
| 116 |
+
q: torch.Tensor,
|
| 117 |
+
k_cache: torch.Tensor,
|
| 118 |
+
v_cache: torch.Tensor,
|
| 119 |
+
req_to_token: torch.Tensor,
|
| 120 |
+
seq_lens: torch.Tensor,
|
| 121 |
+
slot_ids: torch.Tensor,
|
| 122 |
+
block_size: int,
|
| 123 |
+
topk_idx: torch.Tensor,
|
| 124 |
+
sm_scale: float,
|
| 125 |
+
) -> torch.Tensor:
|
| 126 |
+
"""Paged tensor-core block-sparse GQA decode. Returns [B, Hq, D] bf16."""
|
| 127 |
+
|
| 128 |
+
if not _HAS_NATIVE_OPS:
|
| 129 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 130 |
+
out = torch.empty(
|
| 131 |
+
(int(q.shape[0]), int(q.shape[1]), int(q.shape[2])),
|
| 132 |
+
device=q.device,
|
| 133 |
+
dtype=q.dtype,
|
| 134 |
+
)
|
| 135 |
+
ops.msa_decode_sparse_attn_mma_paged(
|
| 136 |
+
q.contiguous(),
|
| 137 |
+
k_cache.contiguous(),
|
| 138 |
+
v_cache.contiguous(),
|
| 139 |
+
req_to_token.contiguous(),
|
| 140 |
+
seq_lens.contiguous(),
|
| 141 |
+
slot_ids.contiguous(),
|
| 142 |
+
topk_idx.contiguous(),
|
| 143 |
+
int(block_size),
|
| 144 |
+
float(sm_scale),
|
| 145 |
+
out,
|
| 146 |
+
)
|
| 147 |
+
return out
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
if _HAS_NATIVE_OPS:
|
| 151 |
+
|
| 152 |
+
@torch.library.register_fake(
|
| 153 |
+
add_op_namespace_prefix("msa_indexer_block_scores")
|
| 154 |
+
)
|
| 155 |
+
def _msa_indexer_block_scores_fake(
|
| 156 |
+
q: torch.Tensor,
|
| 157 |
+
k_pages: torch.Tensor,
|
| 158 |
+
batch_of_q: torch.Tensor,
|
| 159 |
+
cu_q: torch.Tensor,
|
| 160 |
+
cu_k: torch.Tensor,
|
| 161 |
+
cu_pages: torch.Tensor,
|
| 162 |
+
kv_indices: torch.Tensor,
|
| 163 |
+
causal: int,
|
| 164 |
+
scores: torch.Tensor,
|
| 165 |
+
) -> None:
|
| 166 |
+
return None
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
def native_indexer_block_scores(
|
| 170 |
+
q: torch.Tensor,
|
| 171 |
+
k_pages: torch.Tensor,
|
| 172 |
+
batch_of_q: torch.Tensor,
|
| 173 |
+
cu_q: torch.Tensor,
|
| 174 |
+
cu_k: torch.Tensor,
|
| 175 |
+
cu_pages: torch.Tensor,
|
| 176 |
+
kv_indices: torch.Tensor,
|
| 177 |
+
*,
|
| 178 |
+
max_blocks: int,
|
| 179 |
+
causal: bool,
|
| 180 |
+
) -> torch.Tensor:
|
| 181 |
+
"""Block-max QK indexer scores. q/k_pages are bf16 (already dequantized).
|
| 182 |
+
|
| 183 |
+
Returns [Hq, max_blocks, total_q] f32 (-inf where no key is visible).
|
| 184 |
+
"""
|
| 185 |
+
|
| 186 |
+
if not _HAS_NATIVE_OPS:
|
| 187 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 188 |
+
total_q = int(q.shape[0])
|
| 189 |
+
hq = int(q.shape[1])
|
| 190 |
+
scores = torch.full(
|
| 191 |
+
(hq, int(max_blocks), total_q),
|
| 192 |
+
float("-inf"),
|
| 193 |
+
dtype=torch.float32,
|
| 194 |
+
device=q.device,
|
| 195 |
+
)
|
| 196 |
+
ops.msa_indexer_block_scores(
|
| 197 |
+
q.contiguous(),
|
| 198 |
+
k_pages.contiguous(),
|
| 199 |
+
batch_of_q.contiguous(),
|
| 200 |
+
cu_q.contiguous(),
|
| 201 |
+
cu_k.contiguous(),
|
| 202 |
+
cu_pages.contiguous(),
|
| 203 |
+
kv_indices.contiguous(),
|
| 204 |
+
1 if causal else 0,
|
| 205 |
+
scores,
|
| 206 |
+
)
|
| 207 |
+
return scores
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
if _HAS_NATIVE_OPS:
|
| 211 |
+
|
| 212 |
+
@torch.library.register_fake(
|
| 213 |
+
add_op_namespace_prefix("msa_nvfp4_dequant_swizzled_to_bf16")
|
| 214 |
+
)
|
| 215 |
+
def _msa_nvfp4_dequant_swizzled_to_bf16_fake(
|
| 216 |
+
packed: torch.Tensor,
|
| 217 |
+
scale_128x4: torch.Tensor,
|
| 218 |
+
global_scale: float,
|
| 219 |
+
out: torch.Tensor,
|
| 220 |
+
) -> None:
|
| 221 |
+
return None
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
def native_nvfp4_dequant_swizzled_to_bf16(
|
| 225 |
+
packed: torch.Tensor,
|
| 226 |
+
scale_128x4: torch.Tensor,
|
| 227 |
+
global_scale: torch.Tensor | float,
|
| 228 |
+
) -> torch.Tensor:
|
| 229 |
+
"""Expand swizzled NVFP4 weights/KV to dense BF16 with the native CUDA path."""
|
| 230 |
+
|
| 231 |
+
if not _HAS_NATIVE_OPS:
|
| 232 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 233 |
+
if packed.dtype is not torch.uint8:
|
| 234 |
+
raise TypeError("packed must be torch.uint8")
|
| 235 |
+
if scale_128x4.dtype is not torch.uint8:
|
| 236 |
+
raise TypeError("scale_128x4 must be torch.uint8")
|
| 237 |
+
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 238 |
+
out = torch.empty(original_shape, device=packed.device, dtype=torch.bfloat16)
|
| 239 |
+
if isinstance(global_scale, torch.Tensor):
|
| 240 |
+
global_scale_value = float(global_scale.reshape(-1)[0].item())
|
| 241 |
+
else:
|
| 242 |
+
global_scale_value = float(global_scale)
|
| 243 |
+
ops.msa_nvfp4_dequant_swizzled_to_bf16(
|
| 244 |
+
packed.contiguous(),
|
| 245 |
+
scale_128x4.contiguous(),
|
| 246 |
+
global_scale_value,
|
| 247 |
+
out,
|
| 248 |
+
)
|
| 249 |
+
return out
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
__all__ = [
|
| 253 |
+
"has_native_ops",
|
| 254 |
+
"native_topk_from_scores",
|
| 255 |
+
"native_decode_mma_supported",
|
| 256 |
+
"native_decode_sparse_attn_mma_paged",
|
| 257 |
+
"native_indexer_block_scores",
|
| 258 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 259 |
+
]
|
build/torch212-cxx11-cu130-x86_64-linux/_ops.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
import torch
|
| 2 |
-
from . import
|
| 3 |
-
ops = torch.ops.
|
| 4 |
|
| 5 |
def add_op_namespace_prefix(op_name: str):
|
| 6 |
"""
|
| 7 |
Prefix op by namespace.
|
| 8 |
"""
|
| 9 |
-
return f"
|
|
|
|
| 1 |
import torch
|
| 2 |
+
from . import _minimaxai_msa_blackwell_cuda_25b0067
|
| 3 |
+
ops = torch.ops._minimaxai_msa_blackwell_cuda_25b0067
|
| 4 |
|
| 5 |
def add_op_namespace_prefix(op_name: str):
|
| 6 |
"""
|
| 7 |
Prefix op by namespace.
|
| 8 |
"""
|
| 9 |
+
return f"_minimaxai_msa_blackwell_cuda_25b0067::{op_name}"
|
build/torch212-cxx11-cu130-x86_64-linux/api_status.py
CHANGED
|
@@ -22,6 +22,7 @@ V1_AVAILABLE_FUNCTIONS = (
|
|
| 22 |
"nvfp4_global_scale_from_amax",
|
| 23 |
"has_native_ops",
|
| 24 |
"native_topk_from_scores",
|
|
|
|
| 25 |
"flash_decode_with_topk_idx",
|
| 26 |
"flash_decode_with_gqa_share_sparse",
|
| 27 |
"naive_flash_decode_with_topk_idx",
|
|
@@ -55,7 +56,7 @@ _OFFICIAL_API_STATUS = {
|
|
| 55 |
"sparse_atten_nvfp4_kv_func": {
|
| 56 |
"status": "available",
|
| 57 |
"target": "blackwell-prefill-nvfp4",
|
| 58 |
-
"reason": "Official NVFP4 KV prefill API is available via NVFP4 dequantization followed by the Blackwell prefill wrapper.",
|
| 59 |
},
|
| 60 |
"sparse_decode_atten_func": {
|
| 61 |
"status": "available",
|
|
@@ -70,12 +71,12 @@ _OFFICIAL_API_STATUS = {
|
|
| 70 |
"fp4_indexer_block_scores": {
|
| 71 |
"status": "available",
|
| 72 |
"target": "blackwell-fp4-indexer",
|
| 73 |
-
"reason": "Official FP4 block-score API
|
| 74 |
},
|
| 75 |
"build_k2q_csr": {
|
| 76 |
"status": "available",
|
| 77 |
"target": "v1",
|
| 78 |
-
"reason": "
|
| 79 |
},
|
| 80 |
"SparseK2qCsrBuilderSm100": {
|
| 81 |
"status": "available",
|
|
|
|
| 22 |
"nvfp4_global_scale_from_amax",
|
| 23 |
"has_native_ops",
|
| 24 |
"native_topk_from_scores",
|
| 25 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 26 |
"flash_decode_with_topk_idx",
|
| 27 |
"flash_decode_with_gqa_share_sparse",
|
| 28 |
"naive_flash_decode_with_topk_idx",
|
|
|
|
| 56 |
"sparse_atten_nvfp4_kv_func": {
|
| 57 |
"status": "available",
|
| 58 |
"target": "blackwell-prefill-nvfp4",
|
| 59 |
+
"reason": "Official NVFP4 KV prefill API is available via native swizzled NVFP4 dequantization followed by the Blackwell prefill wrapper.",
|
| 60 |
},
|
| 61 |
"sparse_decode_atten_func": {
|
| 62 |
"status": "available",
|
|
|
|
| 71 |
"fp4_indexer_block_scores": {
|
| 72 |
"status": "available",
|
| 73 |
"target": "blackwell-fp4-indexer",
|
| 74 |
+
"reason": "Official FP4 block-score API uses the native Blackwell block-score kernel in built artifacts, with a reference fallback in source-tree mode.",
|
| 75 |
},
|
| 76 |
"build_k2q_csr": {
|
| 77 |
"status": "available",
|
| 78 |
"target": "v1",
|
| 79 |
+
"reason": "CSR construction helper is available for the official prefill API.",
|
| 80 |
},
|
| 81 |
"SparseK2qCsrBuilderSm100": {
|
| 82 |
"status": "available",
|
build/torch212-cxx11-cu130-x86_64-linux/decode/topk_sparse.py
CHANGED
|
@@ -8,6 +8,10 @@ import triton.language as tl
|
|
| 8 |
|
| 9 |
from .._compat import is_hip # vendored: was `from sglang.srt.utils import is_hip`
|
| 10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
from ..common.utils import robust_allocator
|
| 12 |
|
| 13 |
_is_hip = is_hip()
|
|
@@ -341,6 +345,22 @@ def flash_decode_with_gqa_share_sparse(
|
|
| 341 |
# sm scale
|
| 342 |
if sm_scale is None:
|
| 343 |
sm_scale = head_dim**-0.5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 344 |
# Pick NUM_TOPK_CHUNKS so total grid ≈ TARGET_GRID. Same constraints as
|
| 345 |
# flash_decode_with_topk_idx: must be power of 2 (Triton arange) and must
|
| 346 |
# only depend on shape constants (so grid is fixed within a cuda graph).
|
|
|
|
| 8 |
|
| 9 |
from .._compat import is_hip # vendored: was `from sglang.srt.utils import is_hip`
|
| 10 |
|
| 11 |
+
from .._native import (
|
| 12 |
+
native_decode_mma_supported,
|
| 13 |
+
native_decode_sparse_attn_mma_paged,
|
| 14 |
+
)
|
| 15 |
from ..common.utils import robust_allocator
|
| 16 |
|
| 17 |
_is_hip = is_hip()
|
|
|
|
| 345 |
# sm scale
|
| 346 |
if sm_scale is None:
|
| 347 |
sm_scale = head_dim**-0.5
|
| 348 |
+
# Fast path: native tensor-core decode for the M3 MSA shape. Falls through
|
| 349 |
+
# to the Triton kernel for other shapes, sink, or fp8 caches.
|
| 350 |
+
if sink is None and not is_fp8 and native_decode_mma_supported(
|
| 351 |
+
q, k_cache, block_size=block_size
|
| 352 |
+
):
|
| 353 |
+
return native_decode_sparse_attn_mma_paged(
|
| 354 |
+
q,
|
| 355 |
+
k_cache,
|
| 356 |
+
v_cache,
|
| 357 |
+
req_to_token,
|
| 358 |
+
seq_lens,
|
| 359 |
+
slot_ids,
|
| 360 |
+
block_size,
|
| 361 |
+
topk_idx,
|
| 362 |
+
sm_scale,
|
| 363 |
+
)
|
| 364 |
# Pick NUM_TOPK_CHUNKS so total grid ≈ TARGET_GRID. Same constraints as
|
| 365 |
# flash_decode_with_topk_idx: must be power of 2 (Triton arange) and must
|
| 366 |
# only depend on shape constants (so grid is fixed within a cuda graph).
|
build/torch212-cxx11-cu130-x86_64-linux/interface.py
CHANGED
|
@@ -7,6 +7,11 @@ from typing import Optional
|
|
| 7 |
|
| 8 |
import torch
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
from .decode.topk_sparse import flash_decode_with_gqa_share_sparse
|
| 11 |
from .prefill.topk_sparse import flash_prefill_with_gqa_share_sparse
|
| 12 |
from .quantize import Nvfp4QuantizedTensor, dequantize_nvfp4_128x4_to_bf16
|
|
@@ -488,6 +493,12 @@ def _nvfp4_dequant_kv(
|
|
| 488 |
) -> torch.Tensor:
|
| 489 |
if packed.dtype is not torch.uint8:
|
| 490 |
return packed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 491 |
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 492 |
rows = 1
|
| 493 |
for dim in original_shape[:-1]:
|
|
@@ -572,11 +583,12 @@ def fp4_indexer_block_scores(
|
|
| 572 |
qo_offset: Optional[torch.Tensor] = None,
|
| 573 |
scale_layout: str = "preordered_mma",
|
| 574 |
) -> torch.Tensor:
|
| 575 |
-
"""
|
| 576 |
|
| 577 |
Returns the official shape `[Hq, ceil(max_seqlen_k / 128), total_q]`.
|
| 578 |
-
|
| 579 |
-
|
|
|
|
| 580 |
"""
|
| 581 |
|
| 582 |
del qo_offset
|
|
@@ -599,6 +611,29 @@ def fp4_indexer_block_scores(
|
|
| 599 |
|
| 600 |
q = _apply_public_fp4_scale(_unpack_e2m1_fp4(q_fp4), q_scale)
|
| 601 |
k = _apply_public_fp4_scale(_unpack_e2m1_fp4(k_fp4), k_scale)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 602 |
gqa = hq // hkv
|
| 603 |
batch = int(cu_seqlens_q.numel()) - 1
|
| 604 |
cu_q = cu_seqlens_q.to("cpu", non_blocking=False).tolist()
|
|
|
|
| 7 |
|
| 8 |
import torch
|
| 9 |
|
| 10 |
+
from ._native import (
|
| 11 |
+
has_native_ops,
|
| 12 |
+
native_indexer_block_scores,
|
| 13 |
+
native_nvfp4_dequant_swizzled_to_bf16,
|
| 14 |
+
)
|
| 15 |
from .decode.topk_sparse import flash_decode_with_gqa_share_sparse
|
| 16 |
from .prefill.topk_sparse import flash_prefill_with_gqa_share_sparse
|
| 17 |
from .quantize import Nvfp4QuantizedTensor, dequantize_nvfp4_128x4_to_bf16
|
|
|
|
| 493 |
) -> torch.Tensor:
|
| 494 |
if packed.dtype is not torch.uint8:
|
| 495 |
return packed
|
| 496 |
+
if has_native_ops() and packed.is_cuda:
|
| 497 |
+
return native_nvfp4_dequant_swizzled_to_bf16(
|
| 498 |
+
packed,
|
| 499 |
+
scale_128x4,
|
| 500 |
+
global_scale,
|
| 501 |
+
)
|
| 502 |
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 503 |
rows = 1
|
| 504 |
for dim in original_shape[:-1]:
|
|
|
|
| 583 |
qo_offset: Optional[torch.Tensor] = None,
|
| 584 |
scale_layout: str = "preordered_mma",
|
| 585 |
) -> torch.Tensor:
|
| 586 |
+
"""FP4 block-score API for Blackwell.
|
| 587 |
|
| 588 |
Returns the official shape `[Hq, ceil(max_seqlen_k / 128), total_q]`.
|
| 589 |
+
Built artifacts route CUDA tensors through the native Blackwell block-score
|
| 590 |
+
kernel. Source-tree mode uses the reference loop below so the API remains
|
| 591 |
+
testable before the extension is built.
|
| 592 |
"""
|
| 593 |
|
| 594 |
del qo_offset
|
|
|
|
| 611 |
|
| 612 |
q = _apply_public_fp4_scale(_unpack_e2m1_fp4(q_fp4), q_scale)
|
| 613 |
k = _apply_public_fp4_scale(_unpack_e2m1_fp4(k_fp4), k_scale)
|
| 614 |
+
|
| 615 |
+
# Native block-max QK kernel for the cubic scoring loop when available.
|
| 616 |
+
# Same dequant numerics as the reference (bf16 compute); falls back to the
|
| 617 |
+
# Python reference below in source-tree mode.
|
| 618 |
+
if has_native_ops() and q_fp4.is_cuda:
|
| 619 |
+
batch = int(cu_seqlens_q.numel()) - 1
|
| 620 |
+
q_lens = (cu_seqlens_q[1:] - cu_seqlens_q[:-1]).to(torch.int64)
|
| 621 |
+
batch_of_q = torch.repeat_interleave(
|
| 622 |
+
torch.arange(batch, device=q_fp4.device, dtype=torch.int32),
|
| 623 |
+
q_lens,
|
| 624 |
+
)
|
| 625 |
+
return native_indexer_block_scores(
|
| 626 |
+
q.to(torch.bfloat16),
|
| 627 |
+
k.to(torch.bfloat16),
|
| 628 |
+
batch_of_q,
|
| 629 |
+
cu_seqlens_q.to(torch.int32),
|
| 630 |
+
cu_seqlens_k.to(torch.int32),
|
| 631 |
+
cu_page_offsets.to(torch.int32),
|
| 632 |
+
kv_indices.to(torch.int32),
|
| 633 |
+
max_blocks=max_blocks,
|
| 634 |
+
causal=causal,
|
| 635 |
+
)
|
| 636 |
+
|
| 637 |
gqa = hq // hkv
|
| 638 |
batch = int(cu_seqlens_q.numel()) - 1
|
| 639 |
cu_q = cu_seqlens_q.to("cpu", non_blocking=False).tolist()
|
build/torch212-cxx11-cu130-x86_64-linux/metadata.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"name": "minimaxai-msa-blackwell",
|
| 3 |
-
"id": "
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"python-depends": [],
|
|
@@ -14,18 +14,18 @@
|
|
| 14 |
"digest": {
|
| 15 |
"algorithm": "sha256",
|
| 16 |
"files": {
|
| 17 |
-
"__init__.py": "
|
| 18 |
"_compat.py": "5Wy4a96HVMD8omRNsGg8rQJ+0qCCeXiDANk0CuyyP0I=",
|
| 19 |
-
"
|
| 20 |
-
"_native.py": "
|
| 21 |
-
"_ops.py": "
|
| 22 |
-
"api_status.py": "
|
| 23 |
"common/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 24 |
"common/utils.py": "qtwh+wZoySlsWWALvWGVsmcIHKkdZUwePxUZ42tfWxc=",
|
| 25 |
"decode/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 26 |
"decode/flash_with_topk_idx.py": "Pk70+HJ60IKuy4KJC6hPdMtD2BjwPfSMabFiIBODWiQ=",
|
| 27 |
-
"decode/topk_sparse.py": "
|
| 28 |
-
"interface.py": "
|
| 29 |
"minimaxai_msa_blackwell/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY=",
|
| 30 |
"naive/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 31 |
"naive/flash_with_topk_idx.py": "K7WQsRdO9+H2sz7pZ6axnJwE1OmnF0egdKtftHuChig=",
|
|
|
|
| 1 |
{
|
| 2 |
"name": "minimaxai-msa-blackwell",
|
| 3 |
+
"id": "_minimaxai_msa_blackwell_cuda_25b0067",
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"python-depends": [],
|
|
|
|
| 14 |
"digest": {
|
| 15 |
"algorithm": "sha256",
|
| 16 |
"files": {
|
| 17 |
+
"__init__.py": "oPB7xQhjHd9+aLVJkEmJkZOXOwMEarmCdj3SBbhH2bM=",
|
| 18 |
"_compat.py": "5Wy4a96HVMD8omRNsGg8rQJ+0qCCeXiDANk0CuyyP0I=",
|
| 19 |
+
"_minimaxai_msa_blackwell_cuda_25b0067.abi3.so": "LqhiBQoZ3MSwx8v9O1GREvG04FTPwYKhT5KHa0rlufc=",
|
| 20 |
+
"_native.py": "wTh66DiIKxsJ5m8fkAXKSCBYD3CVFVx4PFxceQiwvPY=",
|
| 21 |
+
"_ops.py": "ikU3Lg+kgswKktYjNSq5f4DmgyTR8dnxV8lH3rmOWvk=",
|
| 22 |
+
"api_status.py": "7oZzIkb4fuwkAz3r4Q1slHbOfaP3jwVB647Ok223ATk=",
|
| 23 |
"common/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 24 |
"common/utils.py": "qtwh+wZoySlsWWALvWGVsmcIHKkdZUwePxUZ42tfWxc=",
|
| 25 |
"decode/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 26 |
"decode/flash_with_topk_idx.py": "Pk70+HJ60IKuy4KJC6hPdMtD2BjwPfSMabFiIBODWiQ=",
|
| 27 |
+
"decode/topk_sparse.py": "uINcV9SP5sAf9jYPsPvyQ9lon8sajZ8Qn/yJ+2LA8NU=",
|
| 28 |
+
"interface.py": "jfhBHGyunFF+OdFycJYyptNNIAngKrXY67buTXAN66M=",
|
| 29 |
"minimaxai_msa_blackwell/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY=",
|
| 30 |
"naive/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 31 |
"naive/flash_with_topk_idx.py": "K7WQsRdO9+H2sz7pZ6axnJwE1OmnF0egdKtftHuChig=",
|
build/torch212-cxx11-cu132-x86_64-linux/__init__.py
CHANGED
|
@@ -7,9 +7,12 @@ MiniMax-M3 decode-sparse attention path used by FlashRT's MiniMax Spark runtime.
|
|
| 7 |
|
| 8 |
Implementation status:
|
| 9 |
* native CUDA helper: score -> top-k sparse block ids;
|
| 10 |
-
*
|
|
|
|
|
|
|
|
|
|
| 11 |
* MiniMaxAI/msa compatibility wrappers for CSR prefill, decode, NVFP4 helpers,
|
| 12 |
-
and FP4 block-score
|
| 13 |
|
| 14 |
The upstream MiniMaxAI/msa package is SM100-only; this package is the Blackwell
|
| 15 |
extension path. The public API is Tensor-oriented and independent from
|
|
@@ -48,7 +51,11 @@ from .interface import (
|
|
| 48 |
sparse_atten_nvfp4_kv_func,
|
| 49 |
sparse_decode_atten_func,
|
| 50 |
)
|
| 51 |
-
from ._native import
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
from .naive.flash_with_topk_idx import naive_flash_decode_with_topk_idx
|
| 53 |
from .naive.topk_sparse import naive_flash_decode_with_gqa_share_sparse
|
| 54 |
from .quantize import (
|
|
@@ -88,6 +95,7 @@ __all__ = [
|
|
| 88 |
"flash_decode_with_gqa_share_sparse",
|
| 89 |
"has_native_ops",
|
| 90 |
"native_topk_from_scores",
|
|
|
|
| 91 |
"naive_flash_decode_with_gqa_share_sparse",
|
| 92 |
"naive_flash_decode_with_topk_idx",
|
| 93 |
"get_cu_seqblocks",
|
|
|
|
| 7 |
|
| 8 |
Implementation status:
|
| 9 |
* native CUDA helper: score -> top-k sparse block ids;
|
| 10 |
+
* native CUDA tensor-core sparse decode for the MiniMax-M3 Blackwell shape;
|
| 11 |
+
* native CUDA FP4 block-score indexer;
|
| 12 |
+
* native CUDA helper: swizzled NVFP4 -> BF16 dequant for the W4A16 quality path;
|
| 13 |
+
* Blackwell-validated sparse prefill path;
|
| 14 |
* MiniMaxAI/msa compatibility wrappers for CSR prefill, decode, NVFP4 helpers,
|
| 15 |
+
and FP4 block-score helpers.
|
| 16 |
|
| 17 |
The upstream MiniMaxAI/msa package is SM100-only; this package is the Blackwell
|
| 18 |
extension path. The public API is Tensor-oriented and independent from
|
|
|
|
| 51 |
sparse_atten_nvfp4_kv_func,
|
| 52 |
sparse_decode_atten_func,
|
| 53 |
)
|
| 54 |
+
from ._native import (
|
| 55 |
+
has_native_ops,
|
| 56 |
+
native_nvfp4_dequant_swizzled_to_bf16,
|
| 57 |
+
native_topk_from_scores,
|
| 58 |
+
)
|
| 59 |
from .naive.flash_with_topk_idx import naive_flash_decode_with_topk_idx
|
| 60 |
from .naive.topk_sparse import naive_flash_decode_with_gqa_share_sparse
|
| 61 |
from .quantize import (
|
|
|
|
| 95 |
"flash_decode_with_gqa_share_sparse",
|
| 96 |
"has_native_ops",
|
| 97 |
"native_topk_from_scores",
|
| 98 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 99 |
"naive_flash_decode_with_gqa_share_sparse",
|
| 100 |
"naive_flash_decode_with_topk_idx",
|
| 101 |
"get_cu_seqblocks",
|
build/torch212-cxx11-cu132-x86_64-linux/{_minimaxai_msa_blackwell_cuda_58018d1.abi3.so → _minimaxai_msa_blackwell_cuda_25b0067.abi3.so}
RENAMED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4eb01c1a96c3e640474b3a52f2d38da4be2af0290c4b945c50f90e867d9e907f
|
| 3 |
+
size 744080
|
build/torch212-cxx11-cu132-x86_64-linux/_native.py
CHANGED
|
@@ -62,4 +62,198 @@ def native_topk_from_scores(
|
|
| 62 |
return out
|
| 63 |
|
| 64 |
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
return out
|
| 63 |
|
| 64 |
|
| 65 |
+
if _HAS_NATIVE_OPS:
|
| 66 |
+
|
| 67 |
+
@torch.library.register_fake(
|
| 68 |
+
add_op_namespace_prefix("msa_decode_sparse_attn_mma_paged")
|
| 69 |
+
)
|
| 70 |
+
def _msa_decode_sparse_attn_mma_paged_fake(
|
| 71 |
+
q: torch.Tensor,
|
| 72 |
+
k_cache: torch.Tensor,
|
| 73 |
+
v_cache: torch.Tensor,
|
| 74 |
+
req_to_token: torch.Tensor,
|
| 75 |
+
seq_lens: torch.Tensor,
|
| 76 |
+
slot_ids: torch.Tensor,
|
| 77 |
+
topk_idx: torch.Tensor,
|
| 78 |
+
block_size: int,
|
| 79 |
+
sm_scale: float,
|
| 80 |
+
out: torch.Tensor,
|
| 81 |
+
) -> None:
|
| 82 |
+
return None
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def native_decode_mma_supported(
|
| 86 |
+
q: torch.Tensor,
|
| 87 |
+
k_cache: torch.Tensor,
|
| 88 |
+
*,
|
| 89 |
+
block_size: int,
|
| 90 |
+
) -> bool:
|
| 91 |
+
"""Whether the tensor-core decode kernel applies to these inputs.
|
| 92 |
+
|
| 93 |
+
The mma kernel is specialized for the M3 MSA shape: head_dim 128, GQA
|
| 94 |
+
group (Hq/Hkv) 16, bf16, and a block size that is a multiple of 64.
|
| 95 |
+
"""
|
| 96 |
+
|
| 97 |
+
if not _HAS_NATIVE_OPS:
|
| 98 |
+
return False
|
| 99 |
+
if q.dtype is not torch.bfloat16 or k_cache.dtype is not torch.bfloat16:
|
| 100 |
+
return False
|
| 101 |
+
if q.dim() != 3 or k_cache.dim() != 3:
|
| 102 |
+
return False
|
| 103 |
+
head_dim = int(q.shape[-1])
|
| 104 |
+
num_q_heads = int(q.shape[1])
|
| 105 |
+
num_kv_heads = int(k_cache.shape[1])
|
| 106 |
+
if head_dim != 128 or num_kv_heads <= 0:
|
| 107 |
+
return False
|
| 108 |
+
if num_q_heads % num_kv_heads != 0 or num_q_heads // num_kv_heads != 16:
|
| 109 |
+
return False
|
| 110 |
+
if int(block_size) % 64 != 0:
|
| 111 |
+
return False
|
| 112 |
+
return True
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def native_decode_sparse_attn_mma_paged(
|
| 116 |
+
q: torch.Tensor,
|
| 117 |
+
k_cache: torch.Tensor,
|
| 118 |
+
v_cache: torch.Tensor,
|
| 119 |
+
req_to_token: torch.Tensor,
|
| 120 |
+
seq_lens: torch.Tensor,
|
| 121 |
+
slot_ids: torch.Tensor,
|
| 122 |
+
block_size: int,
|
| 123 |
+
topk_idx: torch.Tensor,
|
| 124 |
+
sm_scale: float,
|
| 125 |
+
) -> torch.Tensor:
|
| 126 |
+
"""Paged tensor-core block-sparse GQA decode. Returns [B, Hq, D] bf16."""
|
| 127 |
+
|
| 128 |
+
if not _HAS_NATIVE_OPS:
|
| 129 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 130 |
+
out = torch.empty(
|
| 131 |
+
(int(q.shape[0]), int(q.shape[1]), int(q.shape[2])),
|
| 132 |
+
device=q.device,
|
| 133 |
+
dtype=q.dtype,
|
| 134 |
+
)
|
| 135 |
+
ops.msa_decode_sparse_attn_mma_paged(
|
| 136 |
+
q.contiguous(),
|
| 137 |
+
k_cache.contiguous(),
|
| 138 |
+
v_cache.contiguous(),
|
| 139 |
+
req_to_token.contiguous(),
|
| 140 |
+
seq_lens.contiguous(),
|
| 141 |
+
slot_ids.contiguous(),
|
| 142 |
+
topk_idx.contiguous(),
|
| 143 |
+
int(block_size),
|
| 144 |
+
float(sm_scale),
|
| 145 |
+
out,
|
| 146 |
+
)
|
| 147 |
+
return out
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
if _HAS_NATIVE_OPS:
|
| 151 |
+
|
| 152 |
+
@torch.library.register_fake(
|
| 153 |
+
add_op_namespace_prefix("msa_indexer_block_scores")
|
| 154 |
+
)
|
| 155 |
+
def _msa_indexer_block_scores_fake(
|
| 156 |
+
q: torch.Tensor,
|
| 157 |
+
k_pages: torch.Tensor,
|
| 158 |
+
batch_of_q: torch.Tensor,
|
| 159 |
+
cu_q: torch.Tensor,
|
| 160 |
+
cu_k: torch.Tensor,
|
| 161 |
+
cu_pages: torch.Tensor,
|
| 162 |
+
kv_indices: torch.Tensor,
|
| 163 |
+
causal: int,
|
| 164 |
+
scores: torch.Tensor,
|
| 165 |
+
) -> None:
|
| 166 |
+
return None
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
def native_indexer_block_scores(
|
| 170 |
+
q: torch.Tensor,
|
| 171 |
+
k_pages: torch.Tensor,
|
| 172 |
+
batch_of_q: torch.Tensor,
|
| 173 |
+
cu_q: torch.Tensor,
|
| 174 |
+
cu_k: torch.Tensor,
|
| 175 |
+
cu_pages: torch.Tensor,
|
| 176 |
+
kv_indices: torch.Tensor,
|
| 177 |
+
*,
|
| 178 |
+
max_blocks: int,
|
| 179 |
+
causal: bool,
|
| 180 |
+
) -> torch.Tensor:
|
| 181 |
+
"""Block-max QK indexer scores. q/k_pages are bf16 (already dequantized).
|
| 182 |
+
|
| 183 |
+
Returns [Hq, max_blocks, total_q] f32 (-inf where no key is visible).
|
| 184 |
+
"""
|
| 185 |
+
|
| 186 |
+
if not _HAS_NATIVE_OPS:
|
| 187 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 188 |
+
total_q = int(q.shape[0])
|
| 189 |
+
hq = int(q.shape[1])
|
| 190 |
+
scores = torch.full(
|
| 191 |
+
(hq, int(max_blocks), total_q),
|
| 192 |
+
float("-inf"),
|
| 193 |
+
dtype=torch.float32,
|
| 194 |
+
device=q.device,
|
| 195 |
+
)
|
| 196 |
+
ops.msa_indexer_block_scores(
|
| 197 |
+
q.contiguous(),
|
| 198 |
+
k_pages.contiguous(),
|
| 199 |
+
batch_of_q.contiguous(),
|
| 200 |
+
cu_q.contiguous(),
|
| 201 |
+
cu_k.contiguous(),
|
| 202 |
+
cu_pages.contiguous(),
|
| 203 |
+
kv_indices.contiguous(),
|
| 204 |
+
1 if causal else 0,
|
| 205 |
+
scores,
|
| 206 |
+
)
|
| 207 |
+
return scores
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
if _HAS_NATIVE_OPS:
|
| 211 |
+
|
| 212 |
+
@torch.library.register_fake(
|
| 213 |
+
add_op_namespace_prefix("msa_nvfp4_dequant_swizzled_to_bf16")
|
| 214 |
+
)
|
| 215 |
+
def _msa_nvfp4_dequant_swizzled_to_bf16_fake(
|
| 216 |
+
packed: torch.Tensor,
|
| 217 |
+
scale_128x4: torch.Tensor,
|
| 218 |
+
global_scale: float,
|
| 219 |
+
out: torch.Tensor,
|
| 220 |
+
) -> None:
|
| 221 |
+
return None
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
def native_nvfp4_dequant_swizzled_to_bf16(
|
| 225 |
+
packed: torch.Tensor,
|
| 226 |
+
scale_128x4: torch.Tensor,
|
| 227 |
+
global_scale: torch.Tensor | float,
|
| 228 |
+
) -> torch.Tensor:
|
| 229 |
+
"""Expand swizzled NVFP4 weights/KV to dense BF16 with the native CUDA path."""
|
| 230 |
+
|
| 231 |
+
if not _HAS_NATIVE_OPS:
|
| 232 |
+
raise RuntimeError("native MiniMax MSA ops are not available in source-tree mode")
|
| 233 |
+
if packed.dtype is not torch.uint8:
|
| 234 |
+
raise TypeError("packed must be torch.uint8")
|
| 235 |
+
if scale_128x4.dtype is not torch.uint8:
|
| 236 |
+
raise TypeError("scale_128x4 must be torch.uint8")
|
| 237 |
+
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 238 |
+
out = torch.empty(original_shape, device=packed.device, dtype=torch.bfloat16)
|
| 239 |
+
if isinstance(global_scale, torch.Tensor):
|
| 240 |
+
global_scale_value = float(global_scale.reshape(-1)[0].item())
|
| 241 |
+
else:
|
| 242 |
+
global_scale_value = float(global_scale)
|
| 243 |
+
ops.msa_nvfp4_dequant_swizzled_to_bf16(
|
| 244 |
+
packed.contiguous(),
|
| 245 |
+
scale_128x4.contiguous(),
|
| 246 |
+
global_scale_value,
|
| 247 |
+
out,
|
| 248 |
+
)
|
| 249 |
+
return out
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
__all__ = [
|
| 253 |
+
"has_native_ops",
|
| 254 |
+
"native_topk_from_scores",
|
| 255 |
+
"native_decode_mma_supported",
|
| 256 |
+
"native_decode_sparse_attn_mma_paged",
|
| 257 |
+
"native_indexer_block_scores",
|
| 258 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 259 |
+
]
|
build/torch212-cxx11-cu132-x86_64-linux/_ops.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
| 1 |
import torch
|
| 2 |
-
from . import
|
| 3 |
-
ops = torch.ops.
|
| 4 |
|
| 5 |
def add_op_namespace_prefix(op_name: str):
|
| 6 |
"""
|
| 7 |
Prefix op by namespace.
|
| 8 |
"""
|
| 9 |
-
return f"
|
|
|
|
| 1 |
import torch
|
| 2 |
+
from . import _minimaxai_msa_blackwell_cuda_25b0067
|
| 3 |
+
ops = torch.ops._minimaxai_msa_blackwell_cuda_25b0067
|
| 4 |
|
| 5 |
def add_op_namespace_prefix(op_name: str):
|
| 6 |
"""
|
| 7 |
Prefix op by namespace.
|
| 8 |
"""
|
| 9 |
+
return f"_minimaxai_msa_blackwell_cuda_25b0067::{op_name}"
|
build/torch212-cxx11-cu132-x86_64-linux/api_status.py
CHANGED
|
@@ -22,6 +22,7 @@ V1_AVAILABLE_FUNCTIONS = (
|
|
| 22 |
"nvfp4_global_scale_from_amax",
|
| 23 |
"has_native_ops",
|
| 24 |
"native_topk_from_scores",
|
|
|
|
| 25 |
"flash_decode_with_topk_idx",
|
| 26 |
"flash_decode_with_gqa_share_sparse",
|
| 27 |
"naive_flash_decode_with_topk_idx",
|
|
@@ -55,7 +56,7 @@ _OFFICIAL_API_STATUS = {
|
|
| 55 |
"sparse_atten_nvfp4_kv_func": {
|
| 56 |
"status": "available",
|
| 57 |
"target": "blackwell-prefill-nvfp4",
|
| 58 |
-
"reason": "Official NVFP4 KV prefill API is available via NVFP4 dequantization followed by the Blackwell prefill wrapper.",
|
| 59 |
},
|
| 60 |
"sparse_decode_atten_func": {
|
| 61 |
"status": "available",
|
|
@@ -70,12 +71,12 @@ _OFFICIAL_API_STATUS = {
|
|
| 70 |
"fp4_indexer_block_scores": {
|
| 71 |
"status": "available",
|
| 72 |
"target": "blackwell-fp4-indexer",
|
| 73 |
-
"reason": "Official FP4 block-score API
|
| 74 |
},
|
| 75 |
"build_k2q_csr": {
|
| 76 |
"status": "available",
|
| 77 |
"target": "v1",
|
| 78 |
-
"reason": "
|
| 79 |
},
|
| 80 |
"SparseK2qCsrBuilderSm100": {
|
| 81 |
"status": "available",
|
|
|
|
| 22 |
"nvfp4_global_scale_from_amax",
|
| 23 |
"has_native_ops",
|
| 24 |
"native_topk_from_scores",
|
| 25 |
+
"native_nvfp4_dequant_swizzled_to_bf16",
|
| 26 |
"flash_decode_with_topk_idx",
|
| 27 |
"flash_decode_with_gqa_share_sparse",
|
| 28 |
"naive_flash_decode_with_topk_idx",
|
|
|
|
| 56 |
"sparse_atten_nvfp4_kv_func": {
|
| 57 |
"status": "available",
|
| 58 |
"target": "blackwell-prefill-nvfp4",
|
| 59 |
+
"reason": "Official NVFP4 KV prefill API is available via native swizzled NVFP4 dequantization followed by the Blackwell prefill wrapper.",
|
| 60 |
},
|
| 61 |
"sparse_decode_atten_func": {
|
| 62 |
"status": "available",
|
|
|
|
| 71 |
"fp4_indexer_block_scores": {
|
| 72 |
"status": "available",
|
| 73 |
"target": "blackwell-fp4-indexer",
|
| 74 |
+
"reason": "Official FP4 block-score API uses the native Blackwell block-score kernel in built artifacts, with a reference fallback in source-tree mode.",
|
| 75 |
},
|
| 76 |
"build_k2q_csr": {
|
| 77 |
"status": "available",
|
| 78 |
"target": "v1",
|
| 79 |
+
"reason": "CSR construction helper is available for the official prefill API.",
|
| 80 |
},
|
| 81 |
"SparseK2qCsrBuilderSm100": {
|
| 82 |
"status": "available",
|
build/torch212-cxx11-cu132-x86_64-linux/decode/topk_sparse.py
CHANGED
|
@@ -8,6 +8,10 @@ import triton.language as tl
|
|
| 8 |
|
| 9 |
from .._compat import is_hip # vendored: was `from sglang.srt.utils import is_hip`
|
| 10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
from ..common.utils import robust_allocator
|
| 12 |
|
| 13 |
_is_hip = is_hip()
|
|
@@ -341,6 +345,22 @@ def flash_decode_with_gqa_share_sparse(
|
|
| 341 |
# sm scale
|
| 342 |
if sm_scale is None:
|
| 343 |
sm_scale = head_dim**-0.5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 344 |
# Pick NUM_TOPK_CHUNKS so total grid ≈ TARGET_GRID. Same constraints as
|
| 345 |
# flash_decode_with_topk_idx: must be power of 2 (Triton arange) and must
|
| 346 |
# only depend on shape constants (so grid is fixed within a cuda graph).
|
|
|
|
| 8 |
|
| 9 |
from .._compat import is_hip # vendored: was `from sglang.srt.utils import is_hip`
|
| 10 |
|
| 11 |
+
from .._native import (
|
| 12 |
+
native_decode_mma_supported,
|
| 13 |
+
native_decode_sparse_attn_mma_paged,
|
| 14 |
+
)
|
| 15 |
from ..common.utils import robust_allocator
|
| 16 |
|
| 17 |
_is_hip = is_hip()
|
|
|
|
| 345 |
# sm scale
|
| 346 |
if sm_scale is None:
|
| 347 |
sm_scale = head_dim**-0.5
|
| 348 |
+
# Fast path: native tensor-core decode for the M3 MSA shape. Falls through
|
| 349 |
+
# to the Triton kernel for other shapes, sink, or fp8 caches.
|
| 350 |
+
if sink is None and not is_fp8 and native_decode_mma_supported(
|
| 351 |
+
q, k_cache, block_size=block_size
|
| 352 |
+
):
|
| 353 |
+
return native_decode_sparse_attn_mma_paged(
|
| 354 |
+
q,
|
| 355 |
+
k_cache,
|
| 356 |
+
v_cache,
|
| 357 |
+
req_to_token,
|
| 358 |
+
seq_lens,
|
| 359 |
+
slot_ids,
|
| 360 |
+
block_size,
|
| 361 |
+
topk_idx,
|
| 362 |
+
sm_scale,
|
| 363 |
+
)
|
| 364 |
# Pick NUM_TOPK_CHUNKS so total grid ≈ TARGET_GRID. Same constraints as
|
| 365 |
# flash_decode_with_topk_idx: must be power of 2 (Triton arange) and must
|
| 366 |
# only depend on shape constants (so grid is fixed within a cuda graph).
|
build/torch212-cxx11-cu132-x86_64-linux/interface.py
CHANGED
|
@@ -7,6 +7,11 @@ from typing import Optional
|
|
| 7 |
|
| 8 |
import torch
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
from .decode.topk_sparse import flash_decode_with_gqa_share_sparse
|
| 11 |
from .prefill.topk_sparse import flash_prefill_with_gqa_share_sparse
|
| 12 |
from .quantize import Nvfp4QuantizedTensor, dequantize_nvfp4_128x4_to_bf16
|
|
@@ -488,6 +493,12 @@ def _nvfp4_dequant_kv(
|
|
| 488 |
) -> torch.Tensor:
|
| 489 |
if packed.dtype is not torch.uint8:
|
| 490 |
return packed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 491 |
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 492 |
rows = 1
|
| 493 |
for dim in original_shape[:-1]:
|
|
@@ -572,11 +583,12 @@ def fp4_indexer_block_scores(
|
|
| 572 |
qo_offset: Optional[torch.Tensor] = None,
|
| 573 |
scale_layout: str = "preordered_mma",
|
| 574 |
) -> torch.Tensor:
|
| 575 |
-
"""
|
| 576 |
|
| 577 |
Returns the official shape `[Hq, ceil(max_seqlen_k / 128), total_q]`.
|
| 578 |
-
|
| 579 |
-
|
|
|
|
| 580 |
"""
|
| 581 |
|
| 582 |
del qo_offset
|
|
@@ -599,6 +611,29 @@ def fp4_indexer_block_scores(
|
|
| 599 |
|
| 600 |
q = _apply_public_fp4_scale(_unpack_e2m1_fp4(q_fp4), q_scale)
|
| 601 |
k = _apply_public_fp4_scale(_unpack_e2m1_fp4(k_fp4), k_scale)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 602 |
gqa = hq // hkv
|
| 603 |
batch = int(cu_seqlens_q.numel()) - 1
|
| 604 |
cu_q = cu_seqlens_q.to("cpu", non_blocking=False).tolist()
|
|
|
|
| 7 |
|
| 8 |
import torch
|
| 9 |
|
| 10 |
+
from ._native import (
|
| 11 |
+
has_native_ops,
|
| 12 |
+
native_indexer_block_scores,
|
| 13 |
+
native_nvfp4_dequant_swizzled_to_bf16,
|
| 14 |
+
)
|
| 15 |
from .decode.topk_sparse import flash_decode_with_gqa_share_sparse
|
| 16 |
from .prefill.topk_sparse import flash_prefill_with_gqa_share_sparse
|
| 17 |
from .quantize import Nvfp4QuantizedTensor, dequantize_nvfp4_128x4_to_bf16
|
|
|
|
| 493 |
) -> torch.Tensor:
|
| 494 |
if packed.dtype is not torch.uint8:
|
| 495 |
return packed
|
| 496 |
+
if has_native_ops() and packed.is_cuda:
|
| 497 |
+
return native_nvfp4_dequant_swizzled_to_bf16(
|
| 498 |
+
packed,
|
| 499 |
+
scale_128x4,
|
| 500 |
+
global_scale,
|
| 501 |
+
)
|
| 502 |
original_shape = tuple(int(v) for v in packed.shape[:-1]) + (int(packed.shape[-1]) * 2,)
|
| 503 |
rows = 1
|
| 504 |
for dim in original_shape[:-1]:
|
|
|
|
| 583 |
qo_offset: Optional[torch.Tensor] = None,
|
| 584 |
scale_layout: str = "preordered_mma",
|
| 585 |
) -> torch.Tensor:
|
| 586 |
+
"""FP4 block-score API for Blackwell.
|
| 587 |
|
| 588 |
Returns the official shape `[Hq, ceil(max_seqlen_k / 128), total_q]`.
|
| 589 |
+
Built artifacts route CUDA tensors through the native Blackwell block-score
|
| 590 |
+
kernel. Source-tree mode uses the reference loop below so the API remains
|
| 591 |
+
testable before the extension is built.
|
| 592 |
"""
|
| 593 |
|
| 594 |
del qo_offset
|
|
|
|
| 611 |
|
| 612 |
q = _apply_public_fp4_scale(_unpack_e2m1_fp4(q_fp4), q_scale)
|
| 613 |
k = _apply_public_fp4_scale(_unpack_e2m1_fp4(k_fp4), k_scale)
|
| 614 |
+
|
| 615 |
+
# Native block-max QK kernel for the cubic scoring loop when available.
|
| 616 |
+
# Same dequant numerics as the reference (bf16 compute); falls back to the
|
| 617 |
+
# Python reference below in source-tree mode.
|
| 618 |
+
if has_native_ops() and q_fp4.is_cuda:
|
| 619 |
+
batch = int(cu_seqlens_q.numel()) - 1
|
| 620 |
+
q_lens = (cu_seqlens_q[1:] - cu_seqlens_q[:-1]).to(torch.int64)
|
| 621 |
+
batch_of_q = torch.repeat_interleave(
|
| 622 |
+
torch.arange(batch, device=q_fp4.device, dtype=torch.int32),
|
| 623 |
+
q_lens,
|
| 624 |
+
)
|
| 625 |
+
return native_indexer_block_scores(
|
| 626 |
+
q.to(torch.bfloat16),
|
| 627 |
+
k.to(torch.bfloat16),
|
| 628 |
+
batch_of_q,
|
| 629 |
+
cu_seqlens_q.to(torch.int32),
|
| 630 |
+
cu_seqlens_k.to(torch.int32),
|
| 631 |
+
cu_page_offsets.to(torch.int32),
|
| 632 |
+
kv_indices.to(torch.int32),
|
| 633 |
+
max_blocks=max_blocks,
|
| 634 |
+
causal=causal,
|
| 635 |
+
)
|
| 636 |
+
|
| 637 |
gqa = hq // hkv
|
| 638 |
batch = int(cu_seqlens_q.numel()) - 1
|
| 639 |
cu_q = cu_seqlens_q.to("cpu", non_blocking=False).tolist()
|
build/torch212-cxx11-cu132-x86_64-linux/metadata.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"name": "minimaxai-msa-blackwell",
|
| 3 |
-
"id": "
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"python-depends": [],
|
|
@@ -14,18 +14,18 @@
|
|
| 14 |
"digest": {
|
| 15 |
"algorithm": "sha256",
|
| 16 |
"files": {
|
| 17 |
-
"__init__.py": "
|
| 18 |
"_compat.py": "5Wy4a96HVMD8omRNsGg8rQJ+0qCCeXiDANk0CuyyP0I=",
|
| 19 |
-
"
|
| 20 |
-
"_native.py": "
|
| 21 |
-
"_ops.py": "
|
| 22 |
-
"api_status.py": "
|
| 23 |
"common/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 24 |
"common/utils.py": "qtwh+wZoySlsWWALvWGVsmcIHKkdZUwePxUZ42tfWxc=",
|
| 25 |
"decode/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 26 |
"decode/flash_with_topk_idx.py": "Pk70+HJ60IKuy4KJC6hPdMtD2BjwPfSMabFiIBODWiQ=",
|
| 27 |
-
"decode/topk_sparse.py": "
|
| 28 |
-
"interface.py": "
|
| 29 |
"minimaxai_msa_blackwell/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY=",
|
| 30 |
"naive/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 31 |
"naive/flash_with_topk_idx.py": "K7WQsRdO9+H2sz7pZ6axnJwE1OmnF0egdKtftHuChig=",
|
|
|
|
| 1 |
{
|
| 2 |
"name": "minimaxai-msa-blackwell",
|
| 3 |
+
"id": "_minimaxai_msa_blackwell_cuda_25b0067",
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"python-depends": [],
|
|
|
|
| 14 |
"digest": {
|
| 15 |
"algorithm": "sha256",
|
| 16 |
"files": {
|
| 17 |
+
"__init__.py": "oPB7xQhjHd9+aLVJkEmJkZOXOwMEarmCdj3SBbhH2bM=",
|
| 18 |
"_compat.py": "5Wy4a96HVMD8omRNsGg8rQJ+0qCCeXiDANk0CuyyP0I=",
|
| 19 |
+
"_minimaxai_msa_blackwell_cuda_25b0067.abi3.so": "TrAcGpbD5kBHSzpS8tONpL4q8CkMS5RcUPkOhn2ekH8=",
|
| 20 |
+
"_native.py": "wTh66DiIKxsJ5m8fkAXKSCBYD3CVFVx4PFxceQiwvPY=",
|
| 21 |
+
"_ops.py": "ikU3Lg+kgswKktYjNSq5f4DmgyTR8dnxV8lH3rmOWvk=",
|
| 22 |
+
"api_status.py": "7oZzIkb4fuwkAz3r4Q1slHbOfaP3jwVB647Ok223ATk=",
|
| 23 |
"common/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 24 |
"common/utils.py": "qtwh+wZoySlsWWALvWGVsmcIHKkdZUwePxUZ42tfWxc=",
|
| 25 |
"decode/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 26 |
"decode/flash_with_topk_idx.py": "Pk70+HJ60IKuy4KJC6hPdMtD2BjwPfSMabFiIBODWiQ=",
|
| 27 |
+
"decode/topk_sparse.py": "uINcV9SP5sAf9jYPsPvyQ9lon8sajZ8Qn/yJ+2LA8NU=",
|
| 28 |
+
"interface.py": "jfhBHGyunFF+OdFycJYyptNNIAngKrXY67buTXAN66M=",
|
| 29 |
"minimaxai_msa_blackwell/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY=",
|
| 30 |
"naive/__init__.py": "bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E=",
|
| 31 |
"naive/flash_with_topk_idx.py": "K7WQsRdO9+H2sz7pZ6axnJwE1OmnF0egdKtftHuChig=",
|