Kernels:
Trusted publisher
Uploaded using `kernel-builder`.
Browse files- benchmarks/benchmark.py +161 -0
- build/torch-stable-abi29-cu128-x86_64-linux/__init__.py +24 -0
- build/torch-stable-abi29-cu128-x86_64-linux/_nvfp4_gemm_cuda_9c5a0e3.abi3.so +3 -0
- build/torch-stable-abi29-cu128-x86_64-linux/_ops.py +9 -0
- build/torch-stable-abi29-cu128-x86_64-linux/_pack.py +110 -0
- build/torch-stable-abi29-cu128-x86_64-linux/functional.py +75 -0
- build/torch-stable-abi29-cu128-x86_64-linux/layers.py +215 -0
- build/torch-stable-abi29-cu128-x86_64-linux/metadata.json +38 -0
- build/torch-stable-abi29-cu128-x86_64-linux/metadata.json.sigstore +1 -0
- build/torch-stable-abi29-cu128-x86_64-linux/nvfp4_gemm/__init__.py +26 -0
- build/torch-stable-abi29-cu130-x86_64-linux/__init__.py +24 -0
- build/torch-stable-abi29-cu130-x86_64-linux/_nvfp4_gemm_cuda_9c5a0e3.abi3.so +3 -0
- build/torch-stable-abi29-cu130-x86_64-linux/_ops.py +9 -0
- build/torch-stable-abi29-cu130-x86_64-linux/_pack.py +110 -0
- build/torch-stable-abi29-cu130-x86_64-linux/functional.py +75 -0
- build/torch-stable-abi29-cu130-x86_64-linux/layers.py +215 -0
- build/torch-stable-abi29-cu130-x86_64-linux/metadata.json +38 -0
- build/torch-stable-abi29-cu130-x86_64-linux/metadata.json.sigstore +1 -0
- build/torch-stable-abi29-cu130-x86_64-linux/nvfp4_gemm/__init__.py +26 -0
- build/torch-stable-abi29-cu132-x86_64-linux/__init__.py +24 -0
- build/torch-stable-abi29-cu132-x86_64-linux/_nvfp4_gemm_cuda_9c5a0e3.abi3.so +3 -0
- build/torch-stable-abi29-cu132-x86_64-linux/_ops.py +9 -0
- build/torch-stable-abi29-cu132-x86_64-linux/_pack.py +110 -0
- build/torch-stable-abi29-cu132-x86_64-linux/functional.py +75 -0
- build/torch-stable-abi29-cu132-x86_64-linux/layers.py +215 -0
- build/torch-stable-abi29-cu132-x86_64-linux/metadata.json +38 -0
- build/torch-stable-abi29-cu132-x86_64-linux/metadata.json.sigstore +1 -0
- build/torch-stable-abi29-cu132-x86_64-linux/nvfp4_gemm/__init__.py +26 -0
benchmarks/benchmark.py
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
|
| 3 |
+
from kernels.benchmark import Benchmark
|
| 4 |
+
|
| 5 |
+
SHAPES = {
|
| 6 |
+
"qkv": (8704, 6656),
|
| 7 |
+
"o": (6656, 4096),
|
| 8 |
+
"mlp": (39936, 6656),
|
| 9 |
+
"down": (6656, 19968),
|
| 10 |
+
"lm_head": (202048, 6656),
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def _dequant(pw):
|
| 15 |
+
grid = torch.tensor(
|
| 16 |
+
[0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0], device=pw.qweight.device
|
| 17 |
+
)
|
| 18 |
+
gs = pw.global_scale.float()
|
| 19 |
+
out = torch.empty(pw.n, pw.k, dtype=torch.float16, device=pw.qweight.device)
|
| 20 |
+
step = 16384
|
| 21 |
+
for i in range(0, pw.n, step):
|
| 22 |
+
qw = pw.qweight[i : i + step]
|
| 23 |
+
nib = torch.stack([qw & 0xF, qw >> 4], dim=-1)
|
| 24 |
+
nib = nib.reshape(qw.shape[0], pw.k).long()
|
| 25 |
+
sign = torch.where((nib & 0x8) != 0, -1.0, 1.0)
|
| 26 |
+
vals = grid[nib & 0x7] * sign
|
| 27 |
+
sf = pw.sf_rowmajor[i : i + step].view(torch.float8_e4m3fn).float()
|
| 28 |
+
scale = sf.repeat_interleave(16, dim=1)
|
| 29 |
+
out[i : i + step] = ((vals * scale) / gs).to(torch.float16)
|
| 30 |
+
return out
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
class NvFP4GemmBenchmark(Benchmark):
|
| 34 |
+
seed: int = 42
|
| 35 |
+
|
| 36 |
+
def _setup_shape(self, name, m):
|
| 37 |
+
n, k = SHAPES[name]
|
| 38 |
+
torch.manual_seed(self.seed)
|
| 39 |
+
w = torch.randn(n, k, dtype=torch.bfloat16) * 0.02
|
| 40 |
+
self.pw = self.kernel.pack(w.to(self.device))
|
| 41 |
+
self.x = torch.randn(m, k, dtype=torch.bfloat16, device=self.device) * 0.125
|
| 42 |
+
self.ref_w = _dequant(self.pw)
|
| 43 |
+
self.xs = self.x.to(torch.float16)
|
| 44 |
+
|
| 45 |
+
def setup_decode_qkv(self):
|
| 46 |
+
self._setup_shape("qkv", 1)
|
| 47 |
+
|
| 48 |
+
def benchmark_decode_qkv(self):
|
| 49 |
+
self.out = self.kernel.gemm(self.pw, self.x)
|
| 50 |
+
|
| 51 |
+
def verify_decode_qkv(self):
|
| 52 |
+
return (self.xs @ self.ref_w.T).to(torch.bfloat16)
|
| 53 |
+
|
| 54 |
+
def setup_decode_o(self):
|
| 55 |
+
self._setup_shape("o", 1)
|
| 56 |
+
|
| 57 |
+
def benchmark_decode_o(self):
|
| 58 |
+
self.out = self.kernel.gemm(self.pw, self.x)
|
| 59 |
+
|
| 60 |
+
def verify_decode_o(self):
|
| 61 |
+
return (self.xs @ self.ref_w.T).to(torch.bfloat16)
|
| 62 |
+
|
| 63 |
+
def setup_decode_mlp(self):
|
| 64 |
+
self._setup_shape("mlp", 1)
|
| 65 |
+
|
| 66 |
+
def benchmark_decode_mlp(self):
|
| 67 |
+
self.out = self.kernel.gemm(self.pw, self.x)
|
| 68 |
+
|
| 69 |
+
def verify_decode_mlp(self):
|
| 70 |
+
return (self.xs @ self.ref_w.T).to(torch.bfloat16)
|
| 71 |
+
|
| 72 |
+
def setup_decode_down(self):
|
| 73 |
+
self._setup_shape("down", 1)
|
| 74 |
+
|
| 75 |
+
def benchmark_decode_down(self):
|
| 76 |
+
self.out = self.kernel.gemm(self.pw, self.x)
|
| 77 |
+
|
| 78 |
+
def verify_decode_down(self):
|
| 79 |
+
return (self.xs @ self.ref_w.T).to(torch.bfloat16)
|
| 80 |
+
|
| 81 |
+
def setup_decode_lm_head(self):
|
| 82 |
+
self._setup_shape("lm_head", 1)
|
| 83 |
+
|
| 84 |
+
def benchmark_decode_lm_head(self):
|
| 85 |
+
self.out = self.kernel.gemm(self.pw, self.x)
|
| 86 |
+
|
| 87 |
+
def verify_decode_lm_head(self):
|
| 88 |
+
return (self.xs @ self.ref_w.T).to(torch.bfloat16)
|
| 89 |
+
|
| 90 |
+
def setup_prefill_mlp(self):
|
| 91 |
+
self._setup_shape("mlp", 512)
|
| 92 |
+
self.x = self.x * 0.2
|
| 93 |
+
xq = self.kernel.quantize_reference(self.x.cpu()).to(self.device)
|
| 94 |
+
self.xs = xq.to(torch.float16)
|
| 95 |
+
|
| 96 |
+
def benchmark_prefill_mlp(self):
|
| 97 |
+
self.out = self.kernel.gemm(self.pw, self.x)
|
| 98 |
+
|
| 99 |
+
def verify_prefill_mlp(self):
|
| 100 |
+
return (self.xs @ self.ref_w.T).to(torch.bfloat16)
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
class NvFP4RawGemvBenchmark(Benchmark):
|
| 104 |
+
seed: int = 42
|
| 105 |
+
|
| 106 |
+
def _setup_shape(self, name):
|
| 107 |
+
n, k = SHAPES[name]
|
| 108 |
+
torch.manual_seed(self.seed)
|
| 109 |
+
w = torch.randn(n, k, dtype=torch.bfloat16) * 0.02
|
| 110 |
+
pw = self.kernel.pack(w.to(self.device))
|
| 111 |
+
self.qw = pw.qweight
|
| 112 |
+
self.sf = pw.sf_rowmajor
|
| 113 |
+
self.alpha = (1.0 / pw.global_scale).float().reshape(1)
|
| 114 |
+
self.x = torch.randn(1, k, dtype=torch.bfloat16, device=self.device) * 0.125
|
| 115 |
+
self.ref_w = _dequant(pw)
|
| 116 |
+
self.xs = self.x.to(torch.float16)
|
| 117 |
+
|
| 118 |
+
def setup_gemv_qkv(self):
|
| 119 |
+
self._setup_shape("qkv")
|
| 120 |
+
|
| 121 |
+
def benchmark_gemv_qkv(self):
|
| 122 |
+
self.out = self.kernel._ops.ops.nvfp4_gemv(self.x, self.qw, self.sf, self.alpha)
|
| 123 |
+
|
| 124 |
+
def verify_gemv_qkv(self):
|
| 125 |
+
return (self.xs @ self.ref_w.T).to(torch.bfloat16)
|
| 126 |
+
|
| 127 |
+
def setup_gemv_o(self):
|
| 128 |
+
self._setup_shape("o")
|
| 129 |
+
|
| 130 |
+
def benchmark_gemv_o(self):
|
| 131 |
+
self.out = self.kernel._ops.ops.nvfp4_gemv(self.x, self.qw, self.sf, self.alpha)
|
| 132 |
+
|
| 133 |
+
def verify_gemv_o(self):
|
| 134 |
+
return (self.xs @ self.ref_w.T).to(torch.bfloat16)
|
| 135 |
+
|
| 136 |
+
def setup_gemv_mlp(self):
|
| 137 |
+
self._setup_shape("mlp")
|
| 138 |
+
|
| 139 |
+
def benchmark_gemv_mlp(self):
|
| 140 |
+
self.out = self.kernel._ops.ops.nvfp4_gemv(self.x, self.qw, self.sf, self.alpha)
|
| 141 |
+
|
| 142 |
+
def verify_gemv_mlp(self):
|
| 143 |
+
return (self.xs @ self.ref_w.T).to(torch.bfloat16)
|
| 144 |
+
|
| 145 |
+
def setup_gemv_down(self):
|
| 146 |
+
self._setup_shape("down")
|
| 147 |
+
|
| 148 |
+
def benchmark_gemv_down(self):
|
| 149 |
+
self.out = self.kernel._ops.ops.nvfp4_gemv(self.x, self.qw, self.sf, self.alpha)
|
| 150 |
+
|
| 151 |
+
def verify_gemv_down(self):
|
| 152 |
+
return (self.xs @ self.ref_w.T).to(torch.bfloat16)
|
| 153 |
+
|
| 154 |
+
def setup_gemv_lm_head(self):
|
| 155 |
+
self._setup_shape("lm_head")
|
| 156 |
+
|
| 157 |
+
def benchmark_gemv_lm_head(self):
|
| 158 |
+
self.out = self.kernel._ops.ops.nvfp4_gemv(self.x, self.qw, self.sf, self.alpha)
|
| 159 |
+
|
| 160 |
+
def verify_gemv_lm_head(self):
|
| 161 |
+
return (self.xs @ self.ref_w.T).to(torch.bfloat16)
|
build/torch-stable-abi29-cu128-x86_64-linux/__init__.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from . import layers
|
| 2 |
+
from .layers import fuse_decode_projections
|
| 3 |
+
from .functional import gemm, gemm_swiglu
|
| 4 |
+
from ._pack import (
|
| 5 |
+
PackedWeight,
|
| 6 |
+
global_scale_for,
|
| 7 |
+
pack,
|
| 8 |
+
pack_swiglu,
|
| 9 |
+
quantize_reference,
|
| 10 |
+
swizzled_sf_shape,
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
__all__ = [
|
| 14 |
+
"PackedWeight",
|
| 15 |
+
"pack",
|
| 16 |
+
"pack_swiglu",
|
| 17 |
+
"quantize_reference",
|
| 18 |
+
"global_scale_for",
|
| 19 |
+
"swizzled_sf_shape",
|
| 20 |
+
"gemm",
|
| 21 |
+
"gemm_swiglu",
|
| 22 |
+
"layers",
|
| 23 |
+
"fuse_decode_projections",
|
| 24 |
+
]
|
build/torch-stable-abi29-cu128-x86_64-linux/_nvfp4_gemm_cuda_9c5a0e3.abi3.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a57bde35bea7918bb524003d916e0074a3b72f5ed76a48c3fcdfe397ae65a8ba
|
| 3 |
+
size 2987544
|
build/torch-stable-abi29-cu128-x86_64-linux/_ops.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from . import _nvfp4_gemm_cuda_9c5a0e3
|
| 3 |
+
ops = torch.ops._nvfp4_gemm_cuda_9c5a0e3
|
| 4 |
+
|
| 5 |
+
def add_op_namespace_prefix(op_name: str):
|
| 6 |
+
"""
|
| 7 |
+
Prefix op by namespace.
|
| 8 |
+
"""
|
| 9 |
+
return f"_nvfp4_gemm_cuda_9c5a0e3::{op_name}"
|
build/torch-stable-abi29-cu128-x86_64-linux/_pack.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dataclasses import dataclass
|
| 2 |
+
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
from ._ops import ops
|
| 6 |
+
|
| 7 |
+
FLOAT8_E4M3_MAX = 448.0
|
| 8 |
+
FLOAT4_E2M1_MAX = 6.0
|
| 9 |
+
SF_VEC_SIZE = 16 # elements sharing one FP8 scale
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def _round_up(x: int, m: int) -> int:
|
| 13 |
+
return (x + m - 1) // m * m
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def swizzled_sf_shape(rows: int, cols: int) -> tuple[int, int]:
|
| 17 |
+
"""Shape of the swizzled scale-factor tensor (dtype int32) produced by
|
| 18 |
+
`scaled_fp4_quant(..., is_sf_swizzled_layout=True)` for a [rows, cols]
|
| 19 |
+
input. Mirrors `computeSwizzledSFShape` in nvfp4_utils.cuh: 128-row tiles,
|
| 20 |
+
4 FP8 scales packed per int32 column."""
|
| 21 |
+
return _round_up(rows, 128), _round_up(cols // SF_VEC_SIZE, 4) // 4
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def global_scale_for(w: torch.Tensor) -> torch.Tensor:
|
| 25 |
+
"""Per-tensor second-level scale: FP8_MAX * FP4_MAX / amax."""
|
| 26 |
+
amax = w.abs().amax().to(torch.float32)
|
| 27 |
+
return (FLOAT8_E4M3_MAX * FLOAT4_E2M1_MAX / amax.clamp(min=1e-12)).reshape(1)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
@dataclass
|
| 31 |
+
class PackedWeight:
|
| 32 |
+
"""NVFP4 representation of a bf16 matrix [n, k]."""
|
| 33 |
+
|
| 34 |
+
qweight: torch.Tensor # uint8 [n, k/2], two e2m1 values per byte
|
| 35 |
+
sf: torch.Tensor # int32, swizzled FP8-E4M3 block scales
|
| 36 |
+
global_scale: torch.Tensor # fp32 [1]
|
| 37 |
+
n: int
|
| 38 |
+
k: int
|
| 39 |
+
swiglu: bool = False
|
| 40 |
+
# uint8 [n, k/16] row-major FP8-E4M3 block scales, consumed by the W4A16
|
| 41 |
+
# GEMV decode path (None when only the swizzled layout is available).
|
| 42 |
+
sf_rowmajor: torch.Tensor | None = None
|
| 43 |
+
|
| 44 |
+
def to(self, device) -> "PackedWeight":
|
| 45 |
+
return PackedWeight(
|
| 46 |
+
qweight=self.qweight.to(device),
|
| 47 |
+
sf=self.sf.to(device),
|
| 48 |
+
global_scale=self.global_scale.to(device),
|
| 49 |
+
n=self.n,
|
| 50 |
+
k=self.k,
|
| 51 |
+
swiglu=self.swiglu,
|
| 52 |
+
sf_rowmajor=(
|
| 53 |
+
None if self.sf_rowmajor is None else self.sf_rowmajor.to(device)
|
| 54 |
+
),
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def pack(
|
| 59 |
+
w: torch.Tensor, device: str | torch.device = "cuda", swiglu: bool = False
|
| 60 |
+
) -> PackedWeight:
|
| 61 |
+
"""Quantize a bf16/fp16 matrix [n, k] to NVFP4 (requires sm100+)."""
|
| 62 |
+
if w.dim() != 2 or not w.is_floating_point():
|
| 63 |
+
raise ValueError("pack() expects a 2-D floating-point weight")
|
| 64 |
+
n, k = w.shape
|
| 65 |
+
if k % SF_VEC_SIZE != 0:
|
| 66 |
+
raise ValueError(f"in_features must be a multiple of {SF_VEC_SIZE}, got {k}")
|
| 67 |
+
wd = w.detach().to(device, torch.bfloat16).contiguous()
|
| 68 |
+
gs = global_scale_for(wd).to(device)
|
| 69 |
+
qweight, sf = ops.scaled_fp4_quant(wd, gs, True)
|
| 70 |
+
# Row-major scales for the W4A16 GEMV decode path; the qweight output is
|
| 71 |
+
# identical to the swizzled call's, so it is discarded.
|
| 72 |
+
_, sf_rowmajor = ops.scaled_fp4_quant(wd, gs, False)
|
| 73 |
+
return PackedWeight(
|
| 74 |
+
qweight=qweight,
|
| 75 |
+
sf=sf,
|
| 76 |
+
global_scale=gs,
|
| 77 |
+
n=n,
|
| 78 |
+
k=k,
|
| 79 |
+
swiglu=swiglu,
|
| 80 |
+
sf_rowmajor=sf_rowmajor,
|
| 81 |
+
)
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def pack_swiglu(
|
| 85 |
+
w_gate: torch.Tensor, w_up: torch.Tensor, device: str | torch.device = "cuda"
|
| 86 |
+
) -> PackedWeight:
|
| 87 |
+
"""Pack gate and up projections [n, k] as one [2n, k] matrix; the GEMM
|
| 88 |
+
output has gate values in columns [0, n) and up in [n, 2n)."""
|
| 89 |
+
if w_gate.shape != w_up.shape:
|
| 90 |
+
raise ValueError("gate and up matrices must have the same shape")
|
| 91 |
+
return pack(torch.cat([w_gate, w_up], dim=0), device=device, swiglu=True)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def quantize_reference(w: torch.Tensor) -> torch.Tensor:
|
| 95 |
+
"""Pure-torch NVFP4 emulation (no GPU kernel): quantize + dequantize to
|
| 96 |
+
the same numerics the kernel produces, for tests and quality analysis."""
|
| 97 |
+
orig_dtype = w.dtype
|
| 98 |
+
wf = w.float()
|
| 99 |
+
gs = global_scale_for(wf) # fp8_max*fp4_max/amax
|
| 100 |
+
n, k = wf.shape
|
| 101 |
+
g = wf.reshape(n, k // SF_VEC_SIZE, SF_VEC_SIZE)
|
| 102 |
+
# Block scale: amax/FP4_MAX * global_scale, stored in FP8-E4M3.
|
| 103 |
+
block_amax = g.abs().amax(-1, keepdim=True)
|
| 104 |
+
sf = (block_amax / FLOAT4_E2M1_MAX) * gs
|
| 105 |
+
sf = sf.to(torch.float8_e4m3fn).float().clamp(min=1e-12)
|
| 106 |
+
scaled = g * (gs / sf)
|
| 107 |
+
# e2m1 grid: {0, .5, 1, 1.5, 2, 3, 4, 6} with signs.
|
| 108 |
+
grid = torch.tensor([0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0])
|
| 109 |
+
q = grid[(scaled.abs().unsqueeze(-1) - grid).abs().argmin(-1)] * scaled.sign()
|
| 110 |
+
return (q * sf / gs).reshape(n, k).to(orig_dtype)
|
build/torch-stable-abi29-cu128-x86_64-linux/functional.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
|
| 3 |
+
from ._ops import add_op_namespace_prefix, ops
|
| 4 |
+
from ._pack import FLOAT4_E2M1_MAX, FLOAT8_E4M3_MAX, PackedWeight, swizzled_sf_shape
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
@torch.library.register_fake(add_op_namespace_prefix("scaled_fp4_quant"))
|
| 8 |
+
def _quant_fake(input, input_global_scale, is_sf_swizzled_layout):
|
| 9 |
+
n = input.size(-1)
|
| 10 |
+
m = input.numel() // n
|
| 11 |
+
out = input.new_empty((m, n // 2), dtype=torch.uint8)
|
| 12 |
+
if is_sf_swizzled_layout:
|
| 13 |
+
sf_m, sf_n = swizzled_sf_shape(m, n)
|
| 14 |
+
sf = input.new_empty((sf_m, sf_n), dtype=torch.int32)
|
| 15 |
+
else:
|
| 16 |
+
sf = input.new_empty((m, n // 16), dtype=torch.uint8)
|
| 17 |
+
return out, sf
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
@torch.library.register_fake(add_op_namespace_prefix("cutlass_scaled_fp4_mm"))
|
| 21 |
+
def _mm_fake(a, b, a_sf, b_sf, alpha):
|
| 22 |
+
return a.new_empty((a.size(0), b.size(0)), dtype=torch.bfloat16)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
@torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemv"))
|
| 26 |
+
def _gemv_fake(a, b, b_sf, alpha):
|
| 27 |
+
return a.new_empty((a.size(0), b.size(0)), dtype=torch.bfloat16)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
@torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemv_swiglu"))
|
| 31 |
+
def _gemv_swiglu_fake(a, b, b_sf, alpha):
|
| 32 |
+
return a.new_empty((a.size(0), b.size(0) // 2), dtype=torch.bfloat16)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
@torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemv_gated"))
|
| 36 |
+
def _gemv_gated_fake(a, g, b, b_sf, alpha):
|
| 37 |
+
return a.new_empty((a.size(0), b.size(0)), dtype=torch.bfloat16)
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def _as_fp8(sf: torch.Tensor) -> torch.Tensor:
|
| 41 |
+
return sf.view(torch.float8_e4m3fn) if sf.dtype == torch.int32 else sf
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def gemm(pw: PackedWeight, x: torch.Tensor) -> torch.Tensor:
|
| 45 |
+
"""y[..., n] = x[..., k] @ W.T with dynamic NVFP4 activation quantization
|
| 46 |
+
(W4A4 on the Blackwell block-scaled tensor cores)."""
|
| 47 |
+
if x.shape[-1] != pw.k:
|
| 48 |
+
raise ValueError(f"expected {pw.k} input features, got {x.shape[-1]}")
|
| 49 |
+
x2 = x.reshape(-1, pw.k)
|
| 50 |
+
if not x2.is_contiguous():
|
| 51 |
+
x2 = x2.contiguous()
|
| 52 |
+
# Decode path: W4A16 GEMV keeps activations in bf16 (no activation
|
| 53 |
+
# quantization). The kernel re-reads the weight per output row, so it is
|
| 54 |
+
# only worthwhile for tiny m; prefill stays on the W4A4 CUTLASS path.
|
| 55 |
+
if x2.size(0) <= 2 and getattr(pw, "sf_rowmajor", None) is not None:
|
| 56 |
+
alpha = (1.0 / pw.global_scale).to(torch.float32).reshape(1)
|
| 57 |
+
y = ops.nvfp4_gemv(x2.to(torch.bfloat16), pw.qweight, pw.sf_rowmajor, alpha)
|
| 58 |
+
return y.reshape(*x.shape[:-1], pw.n)
|
| 59 |
+
a_amax = x2.abs().amax().to(torch.float32)
|
| 60 |
+
a_gs = (FLOAT8_E4M3_MAX * FLOAT4_E2M1_MAX / a_amax.clamp(min=1e-12)).reshape(1)
|
| 61 |
+
aq, a_sf = ops.scaled_fp4_quant(x2.to(torch.bfloat16), a_gs, True)
|
| 62 |
+
alpha = (1.0 / (a_gs * pw.global_scale)).to(torch.float32)
|
| 63 |
+
# The quant op returns swizzled scales packed 4-per-int32; the GEMM takes
|
| 64 |
+
# the same bytes typed as fp8-e4m3.
|
| 65 |
+
y = ops.cutlass_scaled_fp4_mm(aq, pw.qweight, _as_fp8(a_sf), _as_fp8(pw.sf), alpha)
|
| 66 |
+
return y.reshape(*x.shape[:-1], pw.n)
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def gemm_swiglu(pw: PackedWeight, x: torch.Tensor) -> torch.Tensor:
|
| 70 |
+
"""silu(x @ W_gate.T) * (x @ W_up.T) for a SwiGLU-packed matrix."""
|
| 71 |
+
if not pw.swiglu:
|
| 72 |
+
raise ValueError("packed matrix was not packed with pack_swiglu")
|
| 73 |
+
y = gemm(pw, x)
|
| 74 |
+
half = pw.n // 2
|
| 75 |
+
return torch.nn.functional.silu(y[..., :half]) * y[..., half:]
|
build/torch-stable-abi29-cu128-x86_64-linux/layers.py
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
|
| 4 |
+
from .functional import gemm
|
| 5 |
+
from ._ops import ops
|
| 6 |
+
from ._pack import PackedWeight
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class NVFP4Linear(nn.Module):
|
| 10 |
+
can_torch_compile = True
|
| 11 |
+
has_backward = False
|
| 12 |
+
|
| 13 |
+
def forward(self, x):
|
| 14 |
+
pw = PackedWeight(
|
| 15 |
+
qweight=self.weight,
|
| 16 |
+
sf=self.weight_sf,
|
| 17 |
+
global_scale=self.weight_global_scale,
|
| 18 |
+
n=self.out_features,
|
| 19 |
+
k=self.in_features,
|
| 20 |
+
sf_rowmajor=getattr(self, "weight_sf_rowmajor", None),
|
| 21 |
+
)
|
| 22 |
+
return gemm(pw, x)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def _ntokens(x):
|
| 26 |
+
return x.numel() // x.shape[-1]
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def _fused_gemv(module, x):
|
| 30 |
+
return ops.nvfp4_gemv(
|
| 31 |
+
x.reshape(-1, x.shape[-1]).to(torch.bfloat16),
|
| 32 |
+
module.nvfp4_fused_qweight,
|
| 33 |
+
module.nvfp4_fused_sf,
|
| 34 |
+
module.nvfp4_fused_alpha,
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class NVFP4FusedSwiGLUMLP(nn.Module):
|
| 39 |
+
can_torch_compile = True
|
| 40 |
+
has_backward = False
|
| 41 |
+
|
| 42 |
+
def forward(self, x):
|
| 43 |
+
if _ntokens(x) <= 2 and hasattr(self, "nvfp4_fused_qweight"):
|
| 44 |
+
x2 = x.reshape(-1, x.shape[-1]).to(torch.bfloat16)
|
| 45 |
+
h = ops.nvfp4_gemv_swiglu(
|
| 46 |
+
x2,
|
| 47 |
+
self.nvfp4_fused_qweight,
|
| 48 |
+
self.nvfp4_fused_sf,
|
| 49 |
+
self.nvfp4_fused_alpha,
|
| 50 |
+
)
|
| 51 |
+
return self.down_proj(h.reshape(*x.shape[:-1], -1))
|
| 52 |
+
return self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class NVFP4GatedAttention(nn.Module):
|
| 56 |
+
can_torch_compile = True
|
| 57 |
+
has_backward = False
|
| 58 |
+
|
| 59 |
+
def forward(
|
| 60 |
+
self,
|
| 61 |
+
hidden_states,
|
| 62 |
+
position_embeddings=None,
|
| 63 |
+
attention_mask=None,
|
| 64 |
+
past_key_values=None,
|
| 65 |
+
**kwargs,
|
| 66 |
+
):
|
| 67 |
+
from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS
|
| 68 |
+
|
| 69 |
+
input_shape = hidden_states.shape[:-1]
|
| 70 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 71 |
+
og = None
|
| 72 |
+
if _ntokens(hidden_states) <= 2 and hasattr(self, "nvfp4_fused_qweight"):
|
| 73 |
+
fused = _fused_gemv(self, hidden_states)
|
| 74 |
+
q, k, v, *rest = torch.split(fused, self.nvfp4_fused_splits, dim=-1)
|
| 75 |
+
og = rest[0] if rest else None
|
| 76 |
+
else:
|
| 77 |
+
q = self.q_proj(hidden_states)
|
| 78 |
+
k = self.k_proj(hidden_states)
|
| 79 |
+
v = self.v_proj(hidden_states)
|
| 80 |
+
query_states = q.reshape(hidden_shape).transpose(1, 2)
|
| 81 |
+
key_states = k.reshape(hidden_shape).transpose(1, 2)
|
| 82 |
+
value_states = v.reshape(hidden_shape).transpose(1, 2)
|
| 83 |
+
|
| 84 |
+
norm = getattr(self, "qk_norm", None)
|
| 85 |
+
if norm is not None:
|
| 86 |
+
query_states = norm(query_states) * getattr(self, "qk_scale_factor", 1.0)
|
| 87 |
+
key_states = norm(key_states)
|
| 88 |
+
|
| 89 |
+
if position_embeddings is not None:
|
| 90 |
+
cos, sin = position_embeddings
|
| 91 |
+
query_states, key_states = self.nvfp4_rope(
|
| 92 |
+
query_states, key_states, cos, sin
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
if past_key_values is not None:
|
| 96 |
+
key_states, value_states = past_key_values.update(
|
| 97 |
+
key_states, value_states, self.layer_idx
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
attention_interface = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 101 |
+
self.config._attn_implementation, self.nvfp4_eager
|
| 102 |
+
)
|
| 103 |
+
attn_output, attn_weights = attention_interface(
|
| 104 |
+
self,
|
| 105 |
+
query_states,
|
| 106 |
+
key_states,
|
| 107 |
+
value_states,
|
| 108 |
+
attention_mask,
|
| 109 |
+
dropout=self.attention_dropout if self.training else 0.0,
|
| 110 |
+
scaling=self.scaling,
|
| 111 |
+
sliding_window=getattr(self, "sliding_window", None),
|
| 112 |
+
**kwargs,
|
| 113 |
+
)
|
| 114 |
+
|
| 115 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 116 |
+
if og is None and getattr(self, "gate_proj", None) is not None:
|
| 117 |
+
og = self.gate_proj(hidden_states)
|
| 118 |
+
o = self.o_proj
|
| 119 |
+
if og is not None and _ntokens(attn_output) <= 2 and _has_nvfp4(o):
|
| 120 |
+
a2 = attn_output.reshape(-1, attn_output.shape[-1])
|
| 121 |
+
og2 = og.reshape(a2.shape).contiguous()
|
| 122 |
+
alpha = (1.0 / o.weight_global_scale.float()).reshape(1)
|
| 123 |
+
y = ops.nvfp4_gemv_gated(a2, og2, o.weight, o.weight_sf_rowmajor, alpha)
|
| 124 |
+
return y.reshape(*input_shape, -1), attn_weights
|
| 125 |
+
if og is not None:
|
| 126 |
+
attn_output = attn_output * torch.sigmoid(og.reshape(attn_output.shape))
|
| 127 |
+
return o(attn_output), attn_weights
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
def _has_nvfp4(m):
|
| 131 |
+
return m is not None and hasattr(m, "weight_sf_rowmajor")
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def _is_silu(act):
|
| 135 |
+
return isinstance(act, nn.SiLU) or type(act).__name__ == "SiLUActivation"
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def _attach_fused(module, mods):
|
| 139 |
+
# Keep a single packed allocation and expose row views back through the
|
| 140 |
+
# original projection modules. Previously fusion allocated concatenated
|
| 141 |
+
# weights while retaining an independent copy in every projection.
|
| 142 |
+
# Attention and SwiGLU use row-concatenated storage; the latter is handled
|
| 143 |
+
# by the GEMV kernel using the gate/up half offset.
|
| 144 |
+
fused_qweight = torch.cat([m.weight for m in mods], 0).contiguous()
|
| 145 |
+
fused_sf = torch.cat([m.weight_sf_rowmajor for m in mods], 0).contiguous()
|
| 146 |
+
module.nvfp4_fused_qweight = fused_qweight
|
| 147 |
+
module.nvfp4_fused_sf = fused_sf
|
| 148 |
+
module.nvfp4_fused_alpha = torch.cat(
|
| 149 |
+
[
|
| 150 |
+
(1.0 / m.weight_global_scale.float())
|
| 151 |
+
.reshape(1)
|
| 152 |
+
.expand(m.out_features)
|
| 153 |
+
.contiguous()
|
| 154 |
+
for m in mods
|
| 155 |
+
]
|
| 156 |
+
)
|
| 157 |
+
module.nvfp4_fused_splits = [m.out_features for m in mods]
|
| 158 |
+
|
| 159 |
+
offset = 0
|
| 160 |
+
for m in mods:
|
| 161 |
+
end = offset + m.out_features
|
| 162 |
+
m.weight = fused_qweight[offset:end]
|
| 163 |
+
m.weight_sf_rowmajor = fused_sf[offset:end]
|
| 164 |
+
offset = end
|
| 165 |
+
|
| 166 |
+
|
| 167 |
+
def _capture_helpers(cls, rope_fn):
|
| 168 |
+
if getattr(cls, "nvfp4_eager", None) is not None:
|
| 169 |
+
return
|
| 170 |
+
fwd = cls.forward
|
| 171 |
+
names = ("apply_rotary_pos_emb_interleave", "apply_rotary_pos_emb")
|
| 172 |
+
rope = rope_fn or next(
|
| 173 |
+
(fwd.__globals__[n] for n in names if n in fwd.__code__.co_names), None
|
| 174 |
+
)
|
| 175 |
+
cls.nvfp4_rope = staticmethod(rope) if rope is not None else None
|
| 176 |
+
cls.nvfp4_eager = staticmethod(fwd.__globals__["eager_attention_forward"])
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
def _mark(cls, layer_name):
|
| 180 |
+
if getattr(cls, "kernel_layer_name", None) is not None:
|
| 181 |
+
return
|
| 182 |
+
try:
|
| 183 |
+
from kernels import use_kernel_forward_from_hub
|
| 184 |
+
|
| 185 |
+
use_kernel_forward_from_hub(layer_name)(cls)
|
| 186 |
+
except Exception:
|
| 187 |
+
cls.kernel_layer_name = layer_name
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
def fuse_decode_projections(model, rope_fn=None):
|
| 191 |
+
n = 0
|
| 192 |
+
for mod in model.modules():
|
| 193 |
+
qkv = [getattr(mod, p, None) for p in ("q_proj", "k_proj", "v_proj")]
|
| 194 |
+
if (
|
| 195 |
+
all(_has_nvfp4(p) for p in qkv)
|
| 196 |
+
and hasattr(mod, "o_proj")
|
| 197 |
+
and hasattr(mod, "layer_idx")
|
| 198 |
+
):
|
| 199 |
+
gate = getattr(mod, "gate_proj", None)
|
| 200 |
+
_attach_fused(mod, qkv + ([gate] if _has_nvfp4(gate) else []))
|
| 201 |
+
_capture_helpers(type(mod), rope_fn)
|
| 202 |
+
_mark(type(mod), "NVFP4GatedAttention")
|
| 203 |
+
n += 1
|
| 204 |
+
continue
|
| 205 |
+
gu = [getattr(mod, p, None) for p in ("gate_proj", "up_proj")]
|
| 206 |
+
if (
|
| 207 |
+
all(_has_nvfp4(p) for p in gu)
|
| 208 |
+
and hasattr(mod, "down_proj")
|
| 209 |
+
and _is_silu(getattr(mod, "act_fn", None))
|
| 210 |
+
and gu[0].out_features == gu[1].out_features
|
| 211 |
+
):
|
| 212 |
+
_attach_fused(mod, gu)
|
| 213 |
+
_mark(type(mod), "NVFP4SwiGLUMLP")
|
| 214 |
+
n += 1
|
| 215 |
+
return n
|
build/torch-stable-abi29-cu128-x86_64-linux/metadata.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "nvfp4-gemm",
|
| 3 |
+
"id": "_nvfp4_gemm_cuda_9c5a0e3",
|
| 4 |
+
"version": 1,
|
| 5 |
+
"license": "Apache-2.0",
|
| 6 |
+
"upstream": "git+https://github.com/vllm-project/vllm.git",
|
| 7 |
+
"python-depends": [],
|
| 8 |
+
"backend": {
|
| 9 |
+
"type": "cuda",
|
| 10 |
+
"archs": [
|
| 11 |
+
"10.0a",
|
| 12 |
+
"12.0a"
|
| 13 |
+
]
|
| 14 |
+
},
|
| 15 |
+
"digest": {
|
| 16 |
+
"algorithm": "sha256",
|
| 17 |
+
"files": {
|
| 18 |
+
"__init__.py": "ARXik9k13ZmZ/1tDxHgH6bQyJ8Cn6wmCrz5WEM+DABI=",
|
| 19 |
+
"_nvfp4_gemm_cuda_9c5a0e3.abi3.so": "pXveNb6nkYu1JAA9kW4AdKO3L17XakjD/N/jl65lqLo=",
|
| 20 |
+
"_ops.py": "+jBXp3Uoatvj6U0lcsYwN/3KdSd8+Aknhm5T+xbff6w=",
|
| 21 |
+
"_pack.py": "jATF2LhpSLUEiPWSrhsCWeyxIyn80CSy2QJNkKMADlc=",
|
| 22 |
+
"functional.py": "ZTd0hcUOkDdU9ZvpQMPC81KBP3FUvkmfZu7d7mhZRss=",
|
| 23 |
+
"layers.py": "asplwNUY3+drs57APjw3J9kFLtswK9YI0SxRVHZj2Hg=",
|
| 24 |
+
"nvfp4_gemm/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
|
| 25 |
+
}
|
| 26 |
+
},
|
| 27 |
+
"provenance": {
|
| 28 |
+
"kernel-builder": {
|
| 29 |
+
"version": "0.17.0-dev0",
|
| 30 |
+
"sha": "19aaa6421e674e9fecc352bbae6eab81d19a6bf4",
|
| 31 |
+
"dirty": false
|
| 32 |
+
},
|
| 33 |
+
"kernel": {
|
| 34 |
+
"sha": "9c5a0e35e9733ee93d458d2d4d5814f67d209d29",
|
| 35 |
+
"dirty": false
|
| 36 |
+
}
|
| 37 |
+
}
|
| 38 |
+
}
|
build/torch-stable-abi29-cu128-x86_64-linux/metadata.json.sigstore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial":{"certificate":{"rawBytes":"MIIHSjCCBtGgAwIBAgIUS9OSD73Crs3cQlv9jdxLWV7a4AEwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwODA2MTQwMzQ2WhcNMjYwODA2MTQxMzQ2WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7gZqHDNOMOz4Q8FeyZVlihIXU9AvTzg6euBRbzyxDrLTmcVUvJu3N7RJKMEan5CwIH0OALdYikglKoQ2vkhd2KOCBfAwggXsMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQU5z6L3FGXVChZAWCu0GEujVULvPswHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wawYDVR0RAQH/BGEwX4ZdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDkGCisGAQQBg78wAQEEK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wHwYKKwYBBAGDvzABAgQRd29ya2Zsb3dfZGlzcGF0Y2gwNgYKKwYBBAGDvzABAwQoOWM1YTBlMzVlOTczM2VlOTNkNDU4ZDJkNGQ1ODE0ZjY3ZDIwOWQyOTATBgorBgEEAYO/MAEEBAVCdWlsZDArBgorBgEEAYO/MAEFBB1odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eTAdBgorBgEEAYO/MAEGBA9yZWZzL2hlYWRzL21haW4wOwYKKwYBBAGDvzABCAQtDCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMG0GCisGAQQBg78wAQkEXwxdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wAQoEKgwoOWM1YTBlMzVlOTczM2VlOTNkNDU4ZDJkNGQ1ODE0ZjY3ZDIwOWQyOTAbBgorBgEEAYO/MAELBA0MC3NlbGYtaG9zdGVkMEAGCisGAQQBg78wAQwEMgwwaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5MDgGCisGAQQBg78wAQ0EKgwoOWM1YTBlMzVlOTczM2VlOTNkNDU4ZDJkNGQ1ODE0ZjY3ZDIwOWQyOTAfBgorBgEEAYO/MAEOBBEMD3JlZnMvaGVhZHMvbWFpbjAaBgorBgEEAYO/MAEPBAwMCjEwNzE0NzU1MjkwLgYKKwYBBAGDvzABEAQgDB5odHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2UwGAYKKwYBBAGDvzABEQQKDAgyNTcyMDc0MzBtBgorBgEEAYO/MAESBF8MXWh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS8uZ2l0aHViL3dvcmtmbG93cy9idWlsZC55YW1sQHJlZnMvaGVhZHMvbWFpbjA4BgorBgEEAYO/MAETBCoMKDljNWEwZTM1ZTk3MzNlZTkzZDQ1OGQyZDRkNTgxNGY2N2QyMDlkMjkwIQYKKwYBBAGDvzABFAQTDBF3b3JrZmxvd19kaXNwYXRjaDBkBgorBgEEAYO/MAEVBFYMVGh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS9hY3Rpb25zL3J1bnMvMzExMDgyOTgwNDUvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzBGBgorBgEEAYO/MAEYBDgMNnJlcG86aHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHk6cmVmOnJlZnMvaGVhZHMvbWFpbjCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABn9djIroAAAQDAEcwRQIgEpfpnLDesOAQNDUp8m0yF2wvPAFoeOdx9ISDqtauwoMCIQDQatHRh59ieCHLBGQUKrZ+itQ4BYRDw8Iuc68iIN2yqTAKBggqhkjOPQQDAwNnADBkAjB9q9YrxbAcKxC6YxC3iIS5TTtGqrD/0p6yXCn1Rfbj8sVqp2y6XqzqCw27XDOr+/sCMBDJIfFTbRoyAo1CeXvtzjVsg1kyq/coxBG0OYe0MRhCQxi1GlXLNpTgUeljDF5PPA=="}, "tlogEntries":[{"logIndex":"2360822422", "logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion":{"kind":"hashedrekord", "version":"0.0.1"}, "integratedTime":"1786025026", "inclusionPromise":{"signedEntryTimestamp":"MEYCIQD4uRzsrIjcaXHD1riGjwx70gmfNhYNSSKad+gGnL48FwIhAPC/ipDCJKDDJ3faJqNNzxD9ojhpTY7ks80diyGkiA74"}, "inclusionProof":{"logIndex":"2238918160", "rootHash":"Inbkmbis8U2sMiEM6EmTLZwA5s7x9Sik3HRcVtFMZsM=", "treeSize":"2238918170", "hashes":["DLvWUnbgILnx2+gOnJhcAMtoy/dgm6AFYaJFtiwG8Zg=", "zrSnDQOKLAZKUSbtZvNdr806Ret7zVdbR/kbIw8+d6g=", "yIxZWohpF6TmhojqaHkM2V5308xv0dTGBpt62aZIndE=", "s22eUbTXqsYuVO1WL518IVbaqZCnT/gJ8+Cy7ialgsU=", "Boblyud220auq3IRgfn7lwa+B1whTYwPKuWoUUCiG5w=", "yOi1SZCAJyQeGFNfXEyJmZfgE/yHiViHJh7AkVStYx0=", "ZDDgBLJeZMIedbwsKMeIdE+rnhT6LFyxK01q4RQswB8=", "1QfEqQEF22LcM0N+z5i77k0Oy00Arz4yjX7D1LTJP34=", "tSch9ErXVKdLoCFPSZ8D8aLt8T+YHXh/0cV7rQ+HxWc=", "VN19Pd6HJSN2xUEEfXlAK+NBL7uztCXLEaUeuJxgAbY=", "2DzQwQqFGfdTX3BVYQkcDxiT/TBV7lnr+ya29yCNm+o=", "QVx27ou3XJyzOgzVsHRov+ie3M7wOfT492kpmkbAeBo=", "lLhES7her3Dzu/HSMpPVolTSfVQlKbD23EIsEwXq4V4=", "kVyfjHB6dSBvAqnJBVxvTpb/VPDK9zzq5/txahxnbhc=", "u23nWGlBSoQOMevXp72NpPaDjuN0qcB01i17Odcs3Wk=", "i5Zl8FZrDwxCDv2e2DNO2M8JvpR/c11ElvCZS53/teA=", "xH/DCseLHr9eKoYT8qsORZK7zVdEGYWHuVtsVrD95wY="], "checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n2238918170\nInbkmbis8U2sMiEM6EmTLZwA5s7x9Sik3HRcVtFMZsM=\n\n— rekor.sigstore.dev wNI9ajBEAiAN94fxCmq+jARLavCZelggw0xfIsLdrUI02+C1Z6/LsgIgMV4fswAMOmC7Iztunae8RAFJKZhsGEde4JBU7ziBs9s=\n"}}, "canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIyMWJlOWNlMzc3MWUzN2U3MDI3MTk1ZTRkMDMyNDc0MGY0ZWQyMTM0MTE1NzA0MzI0YThkNmM2OTliNDMwMTQyIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUNVeXhrdFFjQWJUZ1ovSjRsRnhXY2hLbHFaWU1kTUY1VUM3SHRQYmNSckRBSWdSdjlaOFZaVE9vTDQ0cldURW51c0h3cU9tWmdrSFg4b2lkUEFGd0Nub0NNPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaFRha05EUW5SSFowRjNTVUpCWjBsVlV6bFBVMFEzTTBOeWN6TmpVV3gyT1dwa2VFeFhWamRoTkVGRmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDlFUVRKTlZGRjNUWHBSTWxkb1kwNU5hbGwzVDBSQk1rMVVVWGhOZWxFeVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVUzWjFweFNFUk9UMDFQZWpSUk9FWmxlVnBXYkdsb1NWaFZPVUYyVkhwbk5tVjFRbElLWW5wNWVFUnlURlJ0WTFaVmRrcDFNMDQzVWtwTFRVVmhialZEZDBsSU1FOUJUR1JaYVd0bmJFdHZVVEoyYTJoa01rdFBRMEptUVhkbloxaHpUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlUxZWpaTUNqTkdSMWhXUTJoYVFWZERkVEJIUlhWcVZsVk1kbEJ6ZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJGM1dVUldVakJTUVZGSUwwSkhSWGRZTkZwa1lVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKb01Wb3laSEJpYldSdFdWZE9iQXBNTW5Sc1kyMDFiR0pJVFhSWk1qbDBZbGhXZFdGWVVqVk1lVFZ1WVZoU2IyUlhTWFprTWpsNVlUSmFjMkl6WkhwTU1rb3hZVmQ0YTB4dWJHaGlWM2hCQ21OdFZtMWplVGx2V2xkR2EyTjVPWFJaVjJ4MVRVUnJSME5wYzBkQlVWRkNaemM0ZDBGUlJVVkxNbWd3WkVoQ2VrOXBPSFprUnpseVdsYzBkVmxYVGpBS1lWYzVkV041Tlc1aFdGSnZaRmRLTVdNeVZubFpNamwxWkVkV2RXUkROV3BpTWpCM1NIZFpTMHQzV1VKQ1FVZEVkbnBCUWtGblVWSmtNamw1WVRKYWN3cGlNMlJtV2tkc2VtTkhSakJaTW1kM1RtZFpTMHQzV1VKQ1FVZEVkbnBCUWtGM1VXOVBWMDB4V1ZSQ2JFMTZWbXhQVkdONlRUSldiRTlVVG10T1JGVTBDbHBFU210T1IxRXhUMFJGTUZwcVdUTmFSRWwzVDFkUmVVOVVRVlJDWjI5eVFtZEZSVUZaVHk5TlFVVkZRa0ZXUTJSWGJITmFSRUZ5UW1kdmNrSm5SVVVLUVZsUEwwMUJSVVpDUWpGdlpGZGtibUZYTlc1YWJVWnFXbE01Y2xwWVNuVmFWM2g2VEZkT2RtSlhNVEZpYld3d1pWUkJaRUpuYjNKQ1owVkZRVmxQTHdwTlFVVkhRa0U1ZVZwWFducE1NbWhzV1ZkU2Vrd3lNV2hoVnpSM1QzZFpTMHQzV1VKQ1FVZEVkbnBCUWtOQlVYUkVRM1J2WkVoU2QyTjZiM1pNTTFKMkNtRXlWblZNYlVacVpFZHNkbUp1VFhWYU1td3dZVWhXYVdSWVRteGpiVTUyWW01U2JHSnVVWFZaTWpsMFRVY3dSME5wYzBkQlVWRkNaemM0ZDBGUmEwVUtXSGQ0WkdGSVVqQmpTRTAyVEhrNWJtRllVbTlrVjBsMVdUSTVkRXd5YURGYU1tUndZbTFrYlZsWFRteE1NblJzWTIwMWJHSklUWFJaTWpsMFlsaFdkUXBoV0ZJMVRIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VERKS01XRlhlR3RNYm14b1lsZDRRV050Vm0xamVUbHZXbGRHYTJONU9YUlpWMngxQ2sxRVowZERhWE5IUVZGUlFtYzNPSGRCVVc5RlMyZDNiMDlYVFRGWlZFSnNUWHBXYkU5VVkzcE5NbFpzVDFST2EwNUVWVFJhUkVwclRrZFJNVTlFUlRBS1dtcFpNMXBFU1hkUFYxRjVUMVJCWWtKbmIzSkNaMFZGUVZsUEwwMUJSVXhDUVRCTlF6Tk9iR0pIV1hSaFJ6bDZaRWRXYTAxRlFVZERhWE5IUVZGUlFncG5OemgzUVZGM1JVMW5kM2RoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NbWd4V2pKa2NHSnRaRzFaVjA1c1RESjBiR050Tld4aVNFMTBDbGt5T1hSaVdGWjFZVmhTTlUxRVowZERhWE5IUVZGUlFtYzNPSGRCVVRCRlMyZDNiMDlYVFRGWlZFSnNUWHBXYkU5VVkzcE5NbFpzVDFST2EwNUVWVFFLV2tSS2EwNUhVVEZQUkVVd1dtcFpNMXBFU1hkUFYxRjVUMVJCWmtKbmIzSkNaMFZGUVZsUEwwMUJSVTlDUWtWTlJETktiRnB1VFhaaFIxWm9Xa2hOZGdwaVYwWndZbXBCWVVKbmIzSkNaMFZGUVZsUEwwMUJSVkJDUVhkTlEycEZkMDU2UlRCT2VsVXhUV3ByZDB4bldVdExkMWxDUWtGSFJIWjZRVUpGUVZGbkNrUkNOVzlrU0ZKM1kzcHZka3d5WkhCa1IyZ3hXV2sxYW1JeU1IWmhTRlp1V2pKc2RWb3lXbWhaTWxWM1IwRlpTMHQzV1VKQ1FVZEVkbnBCUWtWUlVVc0tSRUZuZVU1VVkzbE5SR013VFhwQ2RFSm5iM0pDWjBWRlFWbFBMMDFCUlZOQ1JqaE5XRmRvTUdSSVFucFBhVGgyV2pKc01HRklWbWxNYlU1MllsTTVid3BrVjJSdVlWYzFibHB0Um1wYVV6bHlXbGhLZFZwWGVIcE1WMDUyWWxjeE1XSnRiREJsVXpoMVdqSnNNR0ZJVm1sTU0yUjJZMjEwYldKSE9UTmplVGxwQ21SWGJITmFRelUxV1ZjeGMxRklTbXhhYmsxMllVZFdhRnBJVFhaaVYwWndZbXBCTkVKbmIzSkNaMFZGUVZsUEwwMUJSVlJDUTI5TlMwUnNhazVYUlhjS1dsUk5NVnBVYXpOTmVrNXNXbFJyZWxwRVVURlBSMUY1V2tSU2EwNVVaM2hPUjFreVRqSlJlVTFFYkd0TmFtdDNTVkZaUzB0M1dVSkNRVWRFZG5wQlFncEdRVkZVUkVKR00ySXpTbkphYlhoMlpERTVhMkZZVG5kWldGSnFZVVJDYTBKbmIzSkNaMFZGUVZsUEwwMUJSVlpDUmxsTlZrZG9NR1JJUW5wUGFUaDJDbG95YkRCaFNGWnBURzFPZG1KVE9XOWtWMlJ1WVZjMWJscHRSbXBhVXpseVdsaEtkVnBYZUhwTVYwNTJZbGN4TVdKdGJEQmxVemxvV1ROU2NHSXlOWG9LVEROS01XSnVUWFpOZWtWNFRVUm5lVTlVWjNkT1JGVjJXVmhTTUZwWE1YZGtTRTEyVFZSQlYwSm5iM0pDWjBWRlFWbFBMMDFCUlZkQ1FXZE5RbTVDTVFwWmJYaHdXWHBDUjBKbmIzSkNaMFZGUVZsUEwwMUJSVmxDUkdkTlRtNUtiR05IT0RaaFNGWnVXakpzZFZveVdtaFpNbFYyWVRKV2VXSnRWbk5qZVRGcUNtSXlNWFJrVnpWd1pFaHJObU50Vm0xUGJrcHNXbTVOZG1GSFZtaGFTRTEyWWxkR2NHSnFRMEpwWjFsTFMzZFpRa0pCU0ZkbFVVbEZRV2RTT0VKSWIwRUtaVUZDTWtGT01EbE5SM0pIZUhoRmVWbDRhMlZJU214dVRuZExhVk5zTmpRemFubDBMelJsUzJOdlFYWkxaVFpQUVVGQlFtNDVaR3BKY205QlFVRlJSQXBCUldOM1VsRkpaMFZ3Wm5CdVRFUmxjMDlCVVU1RVZYQTRiVEI1UmpKM2RsQkJSbTlsVDJSNE9VbFRSSEYwWVhWM2IwMURTVkZFVVdGMFNGSm9OVGxwQ21WRFNFeENSMUZWUzNKYUsybDBVVFJDV1ZKRWR6aEpkV00yT0dsSlRqSjVjVlJCUzBKblozRm9hMnBQVUZGUlJFRjNUbTVCUkVKclFXcENPWEU1V1hJS2VHSkJZMHQ0UXpaWmVFTXphVWxUTlZSVWRFZHhja1F2TUhBMmVWaERiakZTWm1KcU9ITldjWEF5ZVRaWWNYcHhRM2N5TjFoRVQzSXJMM05EVFVKRVNncEpaa1pVWWxKdmVVRnZNVU5sV0haMGVtcFdjMmN4YTNseEwyTnZlRUpITUU5WlpUQk5VbWhEVVhocE1VZHNXRXhPY0ZSblZXVnNha1JHTlZCUVFUMDlDaTB0TFMwdFJVNUVJRU5GVWxSSlJrbERRVlJGTFMwdExTMEsifX19fQ=="}], "timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyDADAgEAMIICvwYJKoZIhvcNAQcCoIICsDCCAqwCAQMxDTALBglghkgBZQMEAgEwgbcGCyqGSIb3DQEJEAEEoIGnBIGkMIGhAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgw1pVzNBcFREuotVjBVq4ac24HV/5E7bLCQe5t5jIi0gCFEp1QvjmRM06C3vt6D/r2EYGK947GA8yMDI2MDgwNjE0MDM0NlowAwIBAaAypDAwLjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MRUwEwYDVQQDEwxzaWdzdG9yZS10c2GgADGCAdowggHWAgEBMFEwOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZAIUOhNULwyQYe68wUMvy4qOiyojiwwwCwYJYIZIAWUDBAIBoIH8MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjYwODA2MTQwMzQ2WjAvBgkqhkiG9w0BCQQxIgQg2a7o4bl9utb9zteMoi/0SUUnf8lryCUpvcOKki8hxlcwgY4GCyqGSIb3DQEJEAIvMX8wfTB7MHkEIIX5J7wHq2LKw7RDVsEO/IGyxog/2nq55thw2dE6zQW3MFUwPaQ7MDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAoGCCqGSM49BAMCBGYwZAIwILnROv5qsr9Nt/eVheYqzE1snFA0UyPg7whadKIheNnLy5UxYH/cif1PiRxaYjT1AjA3BTNDpZ4M2k5OpGmoGhYhVmz2t6tQD+ZLpf7+oMmrPVk2zY13GDeBvTcrPCkW2og="}]}}, "messageSignature":{"messageDigest":{"algorithm":"SHA2_256", "digest":"Ib6c43ceN+cCcZXk0DJHQPTtITQRVwQySo1saZtDAUI="}, "signature":"MEUCIQCUyxktQcAbTgZ/J4lFxWchKlqZYMdMF5UC7HtPbcRrDAIgRv9Z8VZTOoL44rWTEnusHwqOmZgkHX8oidPAFwCnoCM="}}
|
build/torch-stable-abi29-cu128-x86_64-linux/nvfp4_gemm/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import ctypes
|
| 2 |
+
import importlib.util
|
| 3 |
+
import sys
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from types import ModuleType
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def _import_from_path(file_path: Path) -> ModuleType:
|
| 9 |
+
# We cannot use the module name as-is, after adding it to `sys.modules`,
|
| 10 |
+
# it would also be used for other imports. So, we make a module name that
|
| 11 |
+
# depends on the path for it to be unique using the hex-encoded hash of
|
| 12 |
+
# the path.
|
| 13 |
+
path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
|
| 14 |
+
module_name = path_hash
|
| 15 |
+
spec = importlib.util.spec_from_file_location(module_name, file_path)
|
| 16 |
+
if spec is None:
|
| 17 |
+
raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
|
| 18 |
+
module = importlib.util.module_from_spec(spec)
|
| 19 |
+
if module is None:
|
| 20 |
+
raise ImportError(f"Cannot load module {module_name} from spec")
|
| 21 |
+
sys.modules[module_name] = module
|
| 22 |
+
spec.loader.exec_module(module) # type: ignore
|
| 23 |
+
return module
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
|
build/torch-stable-abi29-cu130-x86_64-linux/__init__.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from . import layers
|
| 2 |
+
from .layers import fuse_decode_projections
|
| 3 |
+
from .functional import gemm, gemm_swiglu
|
| 4 |
+
from ._pack import (
|
| 5 |
+
PackedWeight,
|
| 6 |
+
global_scale_for,
|
| 7 |
+
pack,
|
| 8 |
+
pack_swiglu,
|
| 9 |
+
quantize_reference,
|
| 10 |
+
swizzled_sf_shape,
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
__all__ = [
|
| 14 |
+
"PackedWeight",
|
| 15 |
+
"pack",
|
| 16 |
+
"pack_swiglu",
|
| 17 |
+
"quantize_reference",
|
| 18 |
+
"global_scale_for",
|
| 19 |
+
"swizzled_sf_shape",
|
| 20 |
+
"gemm",
|
| 21 |
+
"gemm_swiglu",
|
| 22 |
+
"layers",
|
| 23 |
+
"fuse_decode_projections",
|
| 24 |
+
]
|
build/torch-stable-abi29-cu130-x86_64-linux/_nvfp4_gemm_cuda_9c5a0e3.abi3.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:677d4daa14831cb173a766cd1c00ad62e33acffd66504685d841679a53cbd315
|
| 3 |
+
size 3124488
|
build/torch-stable-abi29-cu130-x86_64-linux/_ops.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from . import _nvfp4_gemm_cuda_9c5a0e3
|
| 3 |
+
ops = torch.ops._nvfp4_gemm_cuda_9c5a0e3
|
| 4 |
+
|
| 5 |
+
def add_op_namespace_prefix(op_name: str):
|
| 6 |
+
"""
|
| 7 |
+
Prefix op by namespace.
|
| 8 |
+
"""
|
| 9 |
+
return f"_nvfp4_gemm_cuda_9c5a0e3::{op_name}"
|
build/torch-stable-abi29-cu130-x86_64-linux/_pack.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dataclasses import dataclass
|
| 2 |
+
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
from ._ops import ops
|
| 6 |
+
|
| 7 |
+
FLOAT8_E4M3_MAX = 448.0
|
| 8 |
+
FLOAT4_E2M1_MAX = 6.0
|
| 9 |
+
SF_VEC_SIZE = 16 # elements sharing one FP8 scale
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def _round_up(x: int, m: int) -> int:
|
| 13 |
+
return (x + m - 1) // m * m
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def swizzled_sf_shape(rows: int, cols: int) -> tuple[int, int]:
|
| 17 |
+
"""Shape of the swizzled scale-factor tensor (dtype int32) produced by
|
| 18 |
+
`scaled_fp4_quant(..., is_sf_swizzled_layout=True)` for a [rows, cols]
|
| 19 |
+
input. Mirrors `computeSwizzledSFShape` in nvfp4_utils.cuh: 128-row tiles,
|
| 20 |
+
4 FP8 scales packed per int32 column."""
|
| 21 |
+
return _round_up(rows, 128), _round_up(cols // SF_VEC_SIZE, 4) // 4
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def global_scale_for(w: torch.Tensor) -> torch.Tensor:
|
| 25 |
+
"""Per-tensor second-level scale: FP8_MAX * FP4_MAX / amax."""
|
| 26 |
+
amax = w.abs().amax().to(torch.float32)
|
| 27 |
+
return (FLOAT8_E4M3_MAX * FLOAT4_E2M1_MAX / amax.clamp(min=1e-12)).reshape(1)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
@dataclass
|
| 31 |
+
class PackedWeight:
|
| 32 |
+
"""NVFP4 representation of a bf16 matrix [n, k]."""
|
| 33 |
+
|
| 34 |
+
qweight: torch.Tensor # uint8 [n, k/2], two e2m1 values per byte
|
| 35 |
+
sf: torch.Tensor # int32, swizzled FP8-E4M3 block scales
|
| 36 |
+
global_scale: torch.Tensor # fp32 [1]
|
| 37 |
+
n: int
|
| 38 |
+
k: int
|
| 39 |
+
swiglu: bool = False
|
| 40 |
+
# uint8 [n, k/16] row-major FP8-E4M3 block scales, consumed by the W4A16
|
| 41 |
+
# GEMV decode path (None when only the swizzled layout is available).
|
| 42 |
+
sf_rowmajor: torch.Tensor | None = None
|
| 43 |
+
|
| 44 |
+
def to(self, device) -> "PackedWeight":
|
| 45 |
+
return PackedWeight(
|
| 46 |
+
qweight=self.qweight.to(device),
|
| 47 |
+
sf=self.sf.to(device),
|
| 48 |
+
global_scale=self.global_scale.to(device),
|
| 49 |
+
n=self.n,
|
| 50 |
+
k=self.k,
|
| 51 |
+
swiglu=self.swiglu,
|
| 52 |
+
sf_rowmajor=(
|
| 53 |
+
None if self.sf_rowmajor is None else self.sf_rowmajor.to(device)
|
| 54 |
+
),
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def pack(
|
| 59 |
+
w: torch.Tensor, device: str | torch.device = "cuda", swiglu: bool = False
|
| 60 |
+
) -> PackedWeight:
|
| 61 |
+
"""Quantize a bf16/fp16 matrix [n, k] to NVFP4 (requires sm100+)."""
|
| 62 |
+
if w.dim() != 2 or not w.is_floating_point():
|
| 63 |
+
raise ValueError("pack() expects a 2-D floating-point weight")
|
| 64 |
+
n, k = w.shape
|
| 65 |
+
if k % SF_VEC_SIZE != 0:
|
| 66 |
+
raise ValueError(f"in_features must be a multiple of {SF_VEC_SIZE}, got {k}")
|
| 67 |
+
wd = w.detach().to(device, torch.bfloat16).contiguous()
|
| 68 |
+
gs = global_scale_for(wd).to(device)
|
| 69 |
+
qweight, sf = ops.scaled_fp4_quant(wd, gs, True)
|
| 70 |
+
# Row-major scales for the W4A16 GEMV decode path; the qweight output is
|
| 71 |
+
# identical to the swizzled call's, so it is discarded.
|
| 72 |
+
_, sf_rowmajor = ops.scaled_fp4_quant(wd, gs, False)
|
| 73 |
+
return PackedWeight(
|
| 74 |
+
qweight=qweight,
|
| 75 |
+
sf=sf,
|
| 76 |
+
global_scale=gs,
|
| 77 |
+
n=n,
|
| 78 |
+
k=k,
|
| 79 |
+
swiglu=swiglu,
|
| 80 |
+
sf_rowmajor=sf_rowmajor,
|
| 81 |
+
)
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def pack_swiglu(
|
| 85 |
+
w_gate: torch.Tensor, w_up: torch.Tensor, device: str | torch.device = "cuda"
|
| 86 |
+
) -> PackedWeight:
|
| 87 |
+
"""Pack gate and up projections [n, k] as one [2n, k] matrix; the GEMM
|
| 88 |
+
output has gate values in columns [0, n) and up in [n, 2n)."""
|
| 89 |
+
if w_gate.shape != w_up.shape:
|
| 90 |
+
raise ValueError("gate and up matrices must have the same shape")
|
| 91 |
+
return pack(torch.cat([w_gate, w_up], dim=0), device=device, swiglu=True)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def quantize_reference(w: torch.Tensor) -> torch.Tensor:
|
| 95 |
+
"""Pure-torch NVFP4 emulation (no GPU kernel): quantize + dequantize to
|
| 96 |
+
the same numerics the kernel produces, for tests and quality analysis."""
|
| 97 |
+
orig_dtype = w.dtype
|
| 98 |
+
wf = w.float()
|
| 99 |
+
gs = global_scale_for(wf) # fp8_max*fp4_max/amax
|
| 100 |
+
n, k = wf.shape
|
| 101 |
+
g = wf.reshape(n, k // SF_VEC_SIZE, SF_VEC_SIZE)
|
| 102 |
+
# Block scale: amax/FP4_MAX * global_scale, stored in FP8-E4M3.
|
| 103 |
+
block_amax = g.abs().amax(-1, keepdim=True)
|
| 104 |
+
sf = (block_amax / FLOAT4_E2M1_MAX) * gs
|
| 105 |
+
sf = sf.to(torch.float8_e4m3fn).float().clamp(min=1e-12)
|
| 106 |
+
scaled = g * (gs / sf)
|
| 107 |
+
# e2m1 grid: {0, .5, 1, 1.5, 2, 3, 4, 6} with signs.
|
| 108 |
+
grid = torch.tensor([0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0])
|
| 109 |
+
q = grid[(scaled.abs().unsqueeze(-1) - grid).abs().argmin(-1)] * scaled.sign()
|
| 110 |
+
return (q * sf / gs).reshape(n, k).to(orig_dtype)
|
build/torch-stable-abi29-cu130-x86_64-linux/functional.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
|
| 3 |
+
from ._ops import add_op_namespace_prefix, ops
|
| 4 |
+
from ._pack import FLOAT4_E2M1_MAX, FLOAT8_E4M3_MAX, PackedWeight, swizzled_sf_shape
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
@torch.library.register_fake(add_op_namespace_prefix("scaled_fp4_quant"))
|
| 8 |
+
def _quant_fake(input, input_global_scale, is_sf_swizzled_layout):
|
| 9 |
+
n = input.size(-1)
|
| 10 |
+
m = input.numel() // n
|
| 11 |
+
out = input.new_empty((m, n // 2), dtype=torch.uint8)
|
| 12 |
+
if is_sf_swizzled_layout:
|
| 13 |
+
sf_m, sf_n = swizzled_sf_shape(m, n)
|
| 14 |
+
sf = input.new_empty((sf_m, sf_n), dtype=torch.int32)
|
| 15 |
+
else:
|
| 16 |
+
sf = input.new_empty((m, n // 16), dtype=torch.uint8)
|
| 17 |
+
return out, sf
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
@torch.library.register_fake(add_op_namespace_prefix("cutlass_scaled_fp4_mm"))
|
| 21 |
+
def _mm_fake(a, b, a_sf, b_sf, alpha):
|
| 22 |
+
return a.new_empty((a.size(0), b.size(0)), dtype=torch.bfloat16)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
@torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemv"))
|
| 26 |
+
def _gemv_fake(a, b, b_sf, alpha):
|
| 27 |
+
return a.new_empty((a.size(0), b.size(0)), dtype=torch.bfloat16)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
@torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemv_swiglu"))
|
| 31 |
+
def _gemv_swiglu_fake(a, b, b_sf, alpha):
|
| 32 |
+
return a.new_empty((a.size(0), b.size(0) // 2), dtype=torch.bfloat16)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
@torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemv_gated"))
|
| 36 |
+
def _gemv_gated_fake(a, g, b, b_sf, alpha):
|
| 37 |
+
return a.new_empty((a.size(0), b.size(0)), dtype=torch.bfloat16)
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def _as_fp8(sf: torch.Tensor) -> torch.Tensor:
|
| 41 |
+
return sf.view(torch.float8_e4m3fn) if sf.dtype == torch.int32 else sf
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def gemm(pw: PackedWeight, x: torch.Tensor) -> torch.Tensor:
|
| 45 |
+
"""y[..., n] = x[..., k] @ W.T with dynamic NVFP4 activation quantization
|
| 46 |
+
(W4A4 on the Blackwell block-scaled tensor cores)."""
|
| 47 |
+
if x.shape[-1] != pw.k:
|
| 48 |
+
raise ValueError(f"expected {pw.k} input features, got {x.shape[-1]}")
|
| 49 |
+
x2 = x.reshape(-1, pw.k)
|
| 50 |
+
if not x2.is_contiguous():
|
| 51 |
+
x2 = x2.contiguous()
|
| 52 |
+
# Decode path: W4A16 GEMV keeps activations in bf16 (no activation
|
| 53 |
+
# quantization). The kernel re-reads the weight per output row, so it is
|
| 54 |
+
# only worthwhile for tiny m; prefill stays on the W4A4 CUTLASS path.
|
| 55 |
+
if x2.size(0) <= 2 and getattr(pw, "sf_rowmajor", None) is not None:
|
| 56 |
+
alpha = (1.0 / pw.global_scale).to(torch.float32).reshape(1)
|
| 57 |
+
y = ops.nvfp4_gemv(x2.to(torch.bfloat16), pw.qweight, pw.sf_rowmajor, alpha)
|
| 58 |
+
return y.reshape(*x.shape[:-1], pw.n)
|
| 59 |
+
a_amax = x2.abs().amax().to(torch.float32)
|
| 60 |
+
a_gs = (FLOAT8_E4M3_MAX * FLOAT4_E2M1_MAX / a_amax.clamp(min=1e-12)).reshape(1)
|
| 61 |
+
aq, a_sf = ops.scaled_fp4_quant(x2.to(torch.bfloat16), a_gs, True)
|
| 62 |
+
alpha = (1.0 / (a_gs * pw.global_scale)).to(torch.float32)
|
| 63 |
+
# The quant op returns swizzled scales packed 4-per-int32; the GEMM takes
|
| 64 |
+
# the same bytes typed as fp8-e4m3.
|
| 65 |
+
y = ops.cutlass_scaled_fp4_mm(aq, pw.qweight, _as_fp8(a_sf), _as_fp8(pw.sf), alpha)
|
| 66 |
+
return y.reshape(*x.shape[:-1], pw.n)
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def gemm_swiglu(pw: PackedWeight, x: torch.Tensor) -> torch.Tensor:
|
| 70 |
+
"""silu(x @ W_gate.T) * (x @ W_up.T) for a SwiGLU-packed matrix."""
|
| 71 |
+
if not pw.swiglu:
|
| 72 |
+
raise ValueError("packed matrix was not packed with pack_swiglu")
|
| 73 |
+
y = gemm(pw, x)
|
| 74 |
+
half = pw.n // 2
|
| 75 |
+
return torch.nn.functional.silu(y[..., :half]) * y[..., half:]
|
build/torch-stable-abi29-cu130-x86_64-linux/layers.py
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
|
| 4 |
+
from .functional import gemm
|
| 5 |
+
from ._ops import ops
|
| 6 |
+
from ._pack import PackedWeight
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class NVFP4Linear(nn.Module):
|
| 10 |
+
can_torch_compile = True
|
| 11 |
+
has_backward = False
|
| 12 |
+
|
| 13 |
+
def forward(self, x):
|
| 14 |
+
pw = PackedWeight(
|
| 15 |
+
qweight=self.weight,
|
| 16 |
+
sf=self.weight_sf,
|
| 17 |
+
global_scale=self.weight_global_scale,
|
| 18 |
+
n=self.out_features,
|
| 19 |
+
k=self.in_features,
|
| 20 |
+
sf_rowmajor=getattr(self, "weight_sf_rowmajor", None),
|
| 21 |
+
)
|
| 22 |
+
return gemm(pw, x)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def _ntokens(x):
|
| 26 |
+
return x.numel() // x.shape[-1]
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def _fused_gemv(module, x):
|
| 30 |
+
return ops.nvfp4_gemv(
|
| 31 |
+
x.reshape(-1, x.shape[-1]).to(torch.bfloat16),
|
| 32 |
+
module.nvfp4_fused_qweight,
|
| 33 |
+
module.nvfp4_fused_sf,
|
| 34 |
+
module.nvfp4_fused_alpha,
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class NVFP4FusedSwiGLUMLP(nn.Module):
|
| 39 |
+
can_torch_compile = True
|
| 40 |
+
has_backward = False
|
| 41 |
+
|
| 42 |
+
def forward(self, x):
|
| 43 |
+
if _ntokens(x) <= 2 and hasattr(self, "nvfp4_fused_qweight"):
|
| 44 |
+
x2 = x.reshape(-1, x.shape[-1]).to(torch.bfloat16)
|
| 45 |
+
h = ops.nvfp4_gemv_swiglu(
|
| 46 |
+
x2,
|
| 47 |
+
self.nvfp4_fused_qweight,
|
| 48 |
+
self.nvfp4_fused_sf,
|
| 49 |
+
self.nvfp4_fused_alpha,
|
| 50 |
+
)
|
| 51 |
+
return self.down_proj(h.reshape(*x.shape[:-1], -1))
|
| 52 |
+
return self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class NVFP4GatedAttention(nn.Module):
|
| 56 |
+
can_torch_compile = True
|
| 57 |
+
has_backward = False
|
| 58 |
+
|
| 59 |
+
def forward(
|
| 60 |
+
self,
|
| 61 |
+
hidden_states,
|
| 62 |
+
position_embeddings=None,
|
| 63 |
+
attention_mask=None,
|
| 64 |
+
past_key_values=None,
|
| 65 |
+
**kwargs,
|
| 66 |
+
):
|
| 67 |
+
from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS
|
| 68 |
+
|
| 69 |
+
input_shape = hidden_states.shape[:-1]
|
| 70 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 71 |
+
og = None
|
| 72 |
+
if _ntokens(hidden_states) <= 2 and hasattr(self, "nvfp4_fused_qweight"):
|
| 73 |
+
fused = _fused_gemv(self, hidden_states)
|
| 74 |
+
q, k, v, *rest = torch.split(fused, self.nvfp4_fused_splits, dim=-1)
|
| 75 |
+
og = rest[0] if rest else None
|
| 76 |
+
else:
|
| 77 |
+
q = self.q_proj(hidden_states)
|
| 78 |
+
k = self.k_proj(hidden_states)
|
| 79 |
+
v = self.v_proj(hidden_states)
|
| 80 |
+
query_states = q.reshape(hidden_shape).transpose(1, 2)
|
| 81 |
+
key_states = k.reshape(hidden_shape).transpose(1, 2)
|
| 82 |
+
value_states = v.reshape(hidden_shape).transpose(1, 2)
|
| 83 |
+
|
| 84 |
+
norm = getattr(self, "qk_norm", None)
|
| 85 |
+
if norm is not None:
|
| 86 |
+
query_states = norm(query_states) * getattr(self, "qk_scale_factor", 1.0)
|
| 87 |
+
key_states = norm(key_states)
|
| 88 |
+
|
| 89 |
+
if position_embeddings is not None:
|
| 90 |
+
cos, sin = position_embeddings
|
| 91 |
+
query_states, key_states = self.nvfp4_rope(
|
| 92 |
+
query_states, key_states, cos, sin
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
if past_key_values is not None:
|
| 96 |
+
key_states, value_states = past_key_values.update(
|
| 97 |
+
key_states, value_states, self.layer_idx
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
attention_interface = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 101 |
+
self.config._attn_implementation, self.nvfp4_eager
|
| 102 |
+
)
|
| 103 |
+
attn_output, attn_weights = attention_interface(
|
| 104 |
+
self,
|
| 105 |
+
query_states,
|
| 106 |
+
key_states,
|
| 107 |
+
value_states,
|
| 108 |
+
attention_mask,
|
| 109 |
+
dropout=self.attention_dropout if self.training else 0.0,
|
| 110 |
+
scaling=self.scaling,
|
| 111 |
+
sliding_window=getattr(self, "sliding_window", None),
|
| 112 |
+
**kwargs,
|
| 113 |
+
)
|
| 114 |
+
|
| 115 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 116 |
+
if og is None and getattr(self, "gate_proj", None) is not None:
|
| 117 |
+
og = self.gate_proj(hidden_states)
|
| 118 |
+
o = self.o_proj
|
| 119 |
+
if og is not None and _ntokens(attn_output) <= 2 and _has_nvfp4(o):
|
| 120 |
+
a2 = attn_output.reshape(-1, attn_output.shape[-1])
|
| 121 |
+
og2 = og.reshape(a2.shape).contiguous()
|
| 122 |
+
alpha = (1.0 / o.weight_global_scale.float()).reshape(1)
|
| 123 |
+
y = ops.nvfp4_gemv_gated(a2, og2, o.weight, o.weight_sf_rowmajor, alpha)
|
| 124 |
+
return y.reshape(*input_shape, -1), attn_weights
|
| 125 |
+
if og is not None:
|
| 126 |
+
attn_output = attn_output * torch.sigmoid(og.reshape(attn_output.shape))
|
| 127 |
+
return o(attn_output), attn_weights
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
def _has_nvfp4(m):
|
| 131 |
+
return m is not None and hasattr(m, "weight_sf_rowmajor")
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def _is_silu(act):
|
| 135 |
+
return isinstance(act, nn.SiLU) or type(act).__name__ == "SiLUActivation"
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def _attach_fused(module, mods):
|
| 139 |
+
# Keep a single packed allocation and expose row views back through the
|
| 140 |
+
# original projection modules. Previously fusion allocated concatenated
|
| 141 |
+
# weights while retaining an independent copy in every projection.
|
| 142 |
+
# Attention and SwiGLU use row-concatenated storage; the latter is handled
|
| 143 |
+
# by the GEMV kernel using the gate/up half offset.
|
| 144 |
+
fused_qweight = torch.cat([m.weight for m in mods], 0).contiguous()
|
| 145 |
+
fused_sf = torch.cat([m.weight_sf_rowmajor for m in mods], 0).contiguous()
|
| 146 |
+
module.nvfp4_fused_qweight = fused_qweight
|
| 147 |
+
module.nvfp4_fused_sf = fused_sf
|
| 148 |
+
module.nvfp4_fused_alpha = torch.cat(
|
| 149 |
+
[
|
| 150 |
+
(1.0 / m.weight_global_scale.float())
|
| 151 |
+
.reshape(1)
|
| 152 |
+
.expand(m.out_features)
|
| 153 |
+
.contiguous()
|
| 154 |
+
for m in mods
|
| 155 |
+
]
|
| 156 |
+
)
|
| 157 |
+
module.nvfp4_fused_splits = [m.out_features for m in mods]
|
| 158 |
+
|
| 159 |
+
offset = 0
|
| 160 |
+
for m in mods:
|
| 161 |
+
end = offset + m.out_features
|
| 162 |
+
m.weight = fused_qweight[offset:end]
|
| 163 |
+
m.weight_sf_rowmajor = fused_sf[offset:end]
|
| 164 |
+
offset = end
|
| 165 |
+
|
| 166 |
+
|
| 167 |
+
def _capture_helpers(cls, rope_fn):
|
| 168 |
+
if getattr(cls, "nvfp4_eager", None) is not None:
|
| 169 |
+
return
|
| 170 |
+
fwd = cls.forward
|
| 171 |
+
names = ("apply_rotary_pos_emb_interleave", "apply_rotary_pos_emb")
|
| 172 |
+
rope = rope_fn or next(
|
| 173 |
+
(fwd.__globals__[n] for n in names if n in fwd.__code__.co_names), None
|
| 174 |
+
)
|
| 175 |
+
cls.nvfp4_rope = staticmethod(rope) if rope is not None else None
|
| 176 |
+
cls.nvfp4_eager = staticmethod(fwd.__globals__["eager_attention_forward"])
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
def _mark(cls, layer_name):
|
| 180 |
+
if getattr(cls, "kernel_layer_name", None) is not None:
|
| 181 |
+
return
|
| 182 |
+
try:
|
| 183 |
+
from kernels import use_kernel_forward_from_hub
|
| 184 |
+
|
| 185 |
+
use_kernel_forward_from_hub(layer_name)(cls)
|
| 186 |
+
except Exception:
|
| 187 |
+
cls.kernel_layer_name = layer_name
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
def fuse_decode_projections(model, rope_fn=None):
|
| 191 |
+
n = 0
|
| 192 |
+
for mod in model.modules():
|
| 193 |
+
qkv = [getattr(mod, p, None) for p in ("q_proj", "k_proj", "v_proj")]
|
| 194 |
+
if (
|
| 195 |
+
all(_has_nvfp4(p) for p in qkv)
|
| 196 |
+
and hasattr(mod, "o_proj")
|
| 197 |
+
and hasattr(mod, "layer_idx")
|
| 198 |
+
):
|
| 199 |
+
gate = getattr(mod, "gate_proj", None)
|
| 200 |
+
_attach_fused(mod, qkv + ([gate] if _has_nvfp4(gate) else []))
|
| 201 |
+
_capture_helpers(type(mod), rope_fn)
|
| 202 |
+
_mark(type(mod), "NVFP4GatedAttention")
|
| 203 |
+
n += 1
|
| 204 |
+
continue
|
| 205 |
+
gu = [getattr(mod, p, None) for p in ("gate_proj", "up_proj")]
|
| 206 |
+
if (
|
| 207 |
+
all(_has_nvfp4(p) for p in gu)
|
| 208 |
+
and hasattr(mod, "down_proj")
|
| 209 |
+
and _is_silu(getattr(mod, "act_fn", None))
|
| 210 |
+
and gu[0].out_features == gu[1].out_features
|
| 211 |
+
):
|
| 212 |
+
_attach_fused(mod, gu)
|
| 213 |
+
_mark(type(mod), "NVFP4SwiGLUMLP")
|
| 214 |
+
n += 1
|
| 215 |
+
return n
|
build/torch-stable-abi29-cu130-x86_64-linux/metadata.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "nvfp4-gemm",
|
| 3 |
+
"id": "_nvfp4_gemm_cuda_9c5a0e3",
|
| 4 |
+
"version": 1,
|
| 5 |
+
"license": "Apache-2.0",
|
| 6 |
+
"upstream": "git+https://github.com/vllm-project/vllm.git",
|
| 7 |
+
"python-depends": [],
|
| 8 |
+
"backend": {
|
| 9 |
+
"type": "cuda",
|
| 10 |
+
"archs": [
|
| 11 |
+
"10.0a",
|
| 12 |
+
"12.0a"
|
| 13 |
+
]
|
| 14 |
+
},
|
| 15 |
+
"digest": {
|
| 16 |
+
"algorithm": "sha256",
|
| 17 |
+
"files": {
|
| 18 |
+
"__init__.py": "ARXik9k13ZmZ/1tDxHgH6bQyJ8Cn6wmCrz5WEM+DABI=",
|
| 19 |
+
"_nvfp4_gemm_cuda_9c5a0e3.abi3.so": "Z31NqhSDHLFzp2bNHACtYuM6z/1mUEaF2EFnmlPL0xU=",
|
| 20 |
+
"_ops.py": "+jBXp3Uoatvj6U0lcsYwN/3KdSd8+Aknhm5T+xbff6w=",
|
| 21 |
+
"_pack.py": "jATF2LhpSLUEiPWSrhsCWeyxIyn80CSy2QJNkKMADlc=",
|
| 22 |
+
"functional.py": "ZTd0hcUOkDdU9ZvpQMPC81KBP3FUvkmfZu7d7mhZRss=",
|
| 23 |
+
"layers.py": "asplwNUY3+drs57APjw3J9kFLtswK9YI0SxRVHZj2Hg=",
|
| 24 |
+
"nvfp4_gemm/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
|
| 25 |
+
}
|
| 26 |
+
},
|
| 27 |
+
"provenance": {
|
| 28 |
+
"kernel-builder": {
|
| 29 |
+
"version": "0.17.0-dev0",
|
| 30 |
+
"sha": "19aaa6421e674e9fecc352bbae6eab81d19a6bf4",
|
| 31 |
+
"dirty": false
|
| 32 |
+
},
|
| 33 |
+
"kernel": {
|
| 34 |
+
"sha": "9c5a0e35e9733ee93d458d2d4d5814f67d209d29",
|
| 35 |
+
"dirty": false
|
| 36 |
+
}
|
| 37 |
+
}
|
| 38 |
+
}
|
build/torch-stable-abi29-cu130-x86_64-linux/metadata.json.sigstore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial":{"certificate":{"rawBytes":"MIIHSzCCBtGgAwIBAgIUHAfPbhyAe3cC5esJqPyqePr8GwUwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwODA2MTQwMzQ3WhcNMjYwODA2MTQxMzQ3WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWUCsho2YzsyZePsqOe+UxlvRqdrcSrEw5hWkuhJezhApQK2pVybhQB/CKQDwkqHePS1yPoZMs7arsRTrDvp71KOCBfAwggXsMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUMXuHbek4tvcWcO8sCL27wc77BhwwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wawYDVR0RAQH/BGEwX4ZdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDkGCisGAQQBg78wAQEEK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wHwYKKwYBBAGDvzABAgQRd29ya2Zsb3dfZGlzcGF0Y2gwNgYKKwYBBAGDvzABAwQoOWM1YTBlMzVlOTczM2VlOTNkNDU4ZDJkNGQ1ODE0ZjY3ZDIwOWQyOTATBgorBgEEAYO/MAEEBAVCdWlsZDArBgorBgEEAYO/MAEFBB1odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eTAdBgorBgEEAYO/MAEGBA9yZWZzL2hlYWRzL21haW4wOwYKKwYBBAGDvzABCAQtDCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMG0GCisGAQQBg78wAQkEXwxdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wAQoEKgwoOWM1YTBlMzVlOTczM2VlOTNkNDU4ZDJkNGQ1ODE0ZjY3ZDIwOWQyOTAbBgorBgEEAYO/MAELBA0MC3NlbGYtaG9zdGVkMEAGCisGAQQBg78wAQwEMgwwaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5MDgGCisGAQQBg78wAQ0EKgwoOWM1YTBlMzVlOTczM2VlOTNkNDU4ZDJkNGQ1ODE0ZjY3ZDIwOWQyOTAfBgorBgEEAYO/MAEOBBEMD3JlZnMvaGVhZHMvbWFpbjAaBgorBgEEAYO/MAEPBAwMCjEwNzE0NzU1MjkwLgYKKwYBBAGDvzABEAQgDB5odHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2UwGAYKKwYBBAGDvzABEQQKDAgyNTcyMDc0MzBtBgorBgEEAYO/MAESBF8MXWh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS8uZ2l0aHViL3dvcmtmbG93cy9idWlsZC55YW1sQHJlZnMvaGVhZHMvbWFpbjA4BgorBgEEAYO/MAETBCoMKDljNWEwZTM1ZTk3MzNlZTkzZDQ1OGQyZDRkNTgxNGY2N2QyMDlkMjkwIQYKKwYBBAGDvzABFAQTDBF3b3JrZmxvd19kaXNwYXRjaDBkBgorBgEEAYO/MAEVBFYMVGh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS9hY3Rpb25zL3J1bnMvMzExMDgyOTgwNDUvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzBGBgorBgEEAYO/MAEYBDgMNnJlcG86aHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHk6cmVmOnJlZnMvaGVhZHMvbWFpbjCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABn9djJjQAAAQDAEcwRQIhAIIWCYxW+rI6aaMi9HgD2DleYR6J+F6YqKXUxUv4Z4GmAiAyg9XAQCiB5lJQkeWNWmg/JPDvfOUMGlJVQFdOpjX/bzAKBggqhkjOPQQDAwNoADBlAjAjA7B7LOxYtc7NF049oP6Qo975a2A5zVyU/BWuCOQov+xcw5zDliXhCWXOLNW2BnACMQD0H11DuJC9QXwQNmHwj+A29g/LndNPkjV9AIyBq6hwTfWIEED6AkpjmuOSkbTrm2A="}, "tlogEntries":[{"logIndex":"2360822606", "logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion":{"kind":"hashedrekord", "version":"0.0.1"}, "integratedTime":"1786025027", "inclusionPromise":{"signedEntryTimestamp":"MEQCIALdVIyCoXgz+SjRmxpJQDqgY8ecSWQymgLlX9xe2X61AiAUBt7xZWbAvhvQVPlt5yysMBXgs6LV+l2xYpfTXZ2TMA=="}, "inclusionProof":{"logIndex":"2238918344", "rootHash":"eN8oZuSEFGs70/BLfp19zZEf/Ef5N6oImTmtz+Jny7c=", "treeSize":"2238918358", "hashes":["OD35pd+GVFggfOcYGAvxIqbLmRi+yMYiisbcPtNJdJk=", "ohU4TYqXEjN0FOll1utEBukEQUc2a8glNqdj9lVxaqk=", "HErYWbjZJEkdOhwWC3iOORjGwhaO9z3YtuqIZsf55ek=", "qa31WzmDahZLK7TXE00fLX/3SyJLF2NCAmvEO941Ga4=", "NCmw55uH4clQcrqrPxLkqS6vGExt+NgyLt4oB68au6o=", "m06N3WcrfN7DqNJzhl3g+U0foWjztV58UZHFQYl3DGE=", "Fw0l2YFqeuLVAAuiRC2S6aMQd7o0x2qVKJK00oNkgcM=", "yOi1SZCAJyQeGFNfXEyJmZfgE/yHiViHJh7AkVStYx0=", "ZDDgBLJeZMIedbwsKMeIdE+rnhT6LFyxK01q4RQswB8=", "1QfEqQEF22LcM0N+z5i77k0Oy00Arz4yjX7D1LTJP34=", "tSch9ErXVKdLoCFPSZ8D8aLt8T+YHXh/0cV7rQ+HxWc=", "VN19Pd6HJSN2xUEEfXlAK+NBL7uztCXLEaUeuJxgAbY=", "2DzQwQqFGfdTX3BVYQkcDxiT/TBV7lnr+ya29yCNm+o=", "QVx27ou3XJyzOgzVsHRov+ie3M7wOfT492kpmkbAeBo=", "lLhES7her3Dzu/HSMpPVolTSfVQlKbD23EIsEwXq4V4=", "kVyfjHB6dSBvAqnJBVxvTpb/VPDK9zzq5/txahxnbhc=", "u23nWGlBSoQOMevXp72NpPaDjuN0qcB01i17Odcs3Wk=", "i5Zl8FZrDwxCDv2e2DNO2M8JvpR/c11ElvCZS53/teA=", "xH/DCseLHr9eKoYT8qsORZK7zVdEGYWHuVtsVrD95wY="], "checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n2238918358\neN8oZuSEFGs70/BLfp19zZEf/Ef5N6oImTmtz+Jny7c=\n\n— rekor.sigstore.dev wNI9ajBEAiBaLWisA7jij7yzI4AVOOST7ZFXt3aNtgN0/P2yM2mVmAIgAzBqsGjinhohmAEg/l+k00weJZykRapSeglzTmmpNBw=\n"}}, "canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI5ZGIxY2IxOGEzZGIzMWU5N2E1MjUzMmYzZjcxMzBkNWQxMTYxYWIzNjM3NmZjZTUwNGVlN2YxMDYwZWQxOWM4In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJSHQ1eC83V0FzZWwyaWpqSXl5SGwyclgvUyt3U09jUkVwYUgwalRjeUpmUkFpQjl4SzRERlB4SFdkMjJRZHkyV0o2a3g2Z0lGZ3BpZ2NGczBZbVpGS1MwZFE9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaFRla05EUW5SSFowRjNTVUpCWjBsVlNFRm1VR0pvZVVGbE0yTkROV1Z6U25GUWVYRmxVSEk0UjNkVmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDlFUVRKTlZGRjNUWHBSTTFkb1kwNU5hbGwzVDBSQk1rMVVVWGhOZWxFelYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZYVlVOemFHOHlXWHB6ZVZwbFVITnhUMlVyVlhoc2RsSnhaSEpqVTNKRmR6Vm9WMnNLZFdoS1pYcG9RWEJSU3pKd1ZubGlhRkZDTDBOTFVVUjNhM0ZJWlZCVE1YbFFiMXBOY3pkaGNuTlNWSEpFZG5BM01VdFBRMEptUVhkbloxaHpUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZOV0hWSUNtSmxhelIwZG1OWFkwODRjME5NTWpkM1l6YzNRbWgzZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJGM1dVUldVakJTUVZGSUwwSkhSWGRZTkZwa1lVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKb01Wb3laSEJpYldSdFdWZE9iQXBNTW5Sc1kyMDFiR0pJVFhSWk1qbDBZbGhXZFdGWVVqVk1lVFZ1WVZoU2IyUlhTWFprTWpsNVlUSmFjMkl6WkhwTU1rb3hZVmQ0YTB4dWJHaGlWM2hCQ21OdFZtMWplVGx2V2xkR2EyTjVPWFJaVjJ4MVRVUnJSME5wYzBkQlVWRkNaemM0ZDBGUlJVVkxNbWd3WkVoQ2VrOXBPSFprUnpseVdsYzBkVmxYVGpBS1lWYzVkV041Tlc1aFdGSnZaRmRLTVdNeVZubFpNamwxWkVkV2RXUkROV3BpTWpCM1NIZFpTMHQzV1VKQ1FVZEVkbnBCUWtGblVWSmtNamw1WVRKYWN3cGlNMlJtV2tkc2VtTkhSakJaTW1kM1RtZFpTMHQzV1VKQ1FVZEVkbnBCUWtGM1VXOVBWMDB4V1ZSQ2JFMTZWbXhQVkdONlRUSldiRTlVVG10T1JGVTBDbHBFU210T1IxRXhUMFJGTUZwcVdUTmFSRWwzVDFkUmVVOVVRVlJDWjI5eVFtZEZSVUZaVHk5TlFVVkZRa0ZXUTJSWGJITmFSRUZ5UW1kdmNrSm5SVVVLUVZsUEwwMUJSVVpDUWpGdlpGZGtibUZYTlc1YWJVWnFXbE01Y2xwWVNuVmFWM2g2VEZkT2RtSlhNVEZpYld3d1pWUkJaRUpuYjNKQ1owVkZRVmxQTHdwTlFVVkhRa0U1ZVZwWFducE1NbWhzV1ZkU2Vrd3lNV2hoVnpSM1QzZFpTMHQzV1VKQ1FVZEVkbnBCUWtOQlVYUkVRM1J2WkVoU2QyTjZiM1pNTTFKMkNtRXlWblZNYlVacVpFZHNkbUp1VFhWYU1td3dZVWhXYVdSWVRteGpiVTUyWW01U2JHSnVVWFZaTWpsMFRVY3dSME5wYzBkQlVWRkNaemM0ZDBGUmEwVUtXSGQ0WkdGSVVqQmpTRTAyVEhrNWJtRllVbTlrVjBsMVdUSTVkRXd5YURGYU1tUndZbTFrYlZsWFRteE1NblJzWTIwMWJHSklUWFJaTWpsMFlsaFdkUXBoV0ZJMVRIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VERKS01XRlhlR3RNYm14b1lsZDRRV050Vm0xamVUbHZXbGRHYTJONU9YUlpWMngxQ2sxRVowZERhWE5IUVZGUlFtYzNPSGRCVVc5RlMyZDNiMDlYVFRGWlZFSnNUWHBXYkU5VVkzcE5NbFpzVDFST2EwNUVWVFJhUkVwclRrZFJNVTlFUlRBS1dtcFpNMXBFU1hkUFYxRjVUMVJCWWtKbmIzSkNaMFZGUVZsUEwwMUJSVXhDUVRCTlF6Tk9iR0pIV1hSaFJ6bDZaRWRXYTAxRlFVZERhWE5IUVZGUlFncG5OemgzUVZGM1JVMW5kM2RoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NbWd4V2pKa2NHSnRaRzFaVjA1c1RESjBiR050Tld4aVNFMTBDbGt5T1hSaVdGWjFZVmhTTlUxRVowZERhWE5IUVZGUlFtYzNPSGRCVVRCRlMyZDNiMDlYVFRGWlZFSnNUWHBXYkU5VVkzcE5NbFpzVDFST2EwNUVWVFFLV2tSS2EwNUhVVEZQUkVVd1dtcFpNMXBFU1hkUFYxRjVUMVJCWmtKbmIzSkNaMFZGUVZsUEwwMUJSVTlDUWtWTlJETktiRnB1VFhaaFIxWm9Xa2hOZGdwaVYwWndZbXBCWVVKbmIzSkNaMFZGUVZsUEwwMUJSVkJDUVhkTlEycEZkMDU2UlRCT2VsVXhUV3ByZDB4bldVdExkMWxDUWtGSFJIWjZRVUpGUVZGbkNrUkNOVzlrU0ZKM1kzcHZka3d5WkhCa1IyZ3hXV2sxYW1JeU1IWmhTRlp1V2pKc2RWb3lXbWhaTWxWM1IwRlpTMHQzV1VKQ1FVZEVkbnBCUWtWUlVVc0tSRUZuZVU1VVkzbE5SR013VFhwQ2RFSm5iM0pDWjBWRlFWbFBMMDFCUlZOQ1JqaE5XRmRvTUdSSVFucFBhVGgyV2pKc01HRklWbWxNYlU1MllsTTVid3BrVjJSdVlWYzFibHB0Um1wYVV6bHlXbGhLZFZwWGVIcE1WMDUyWWxjeE1XSnRiREJsVXpoMVdqSnNNR0ZJVm1sTU0yUjJZMjEwYldKSE9UTmplVGxwQ21SWGJITmFRelUxV1ZjeGMxRklTbXhhYmsxMllVZFdhRnBJVFhaaVYwWndZbXBCTkVKbmIzSkNaMFZGUVZsUEwwMUJSVlJDUTI5TlMwUnNhazVYUlhjS1dsUk5NVnBVYXpOTmVrNXNXbFJyZWxwRVVURlBSMUY1V2tSU2EwNVVaM2hPUjFreVRqSlJlVTFFYkd0TmFtdDNTVkZaUzB0M1dVSkNRVWRFZG5wQlFncEdRVkZVUkVKR00ySXpTbkphYlhoMlpERTVhMkZZVG5kWldGSnFZVVJDYTBKbmIzSkNaMFZGUVZsUEwwMUJSVlpDUmxsTlZrZG9NR1JJUW5wUGFUaDJDbG95YkRCaFNGWnBURzFPZG1KVE9XOWtWMlJ1WVZjMWJscHRSbXBhVXpseVdsaEtkVnBYZUhwTVYwNTJZbGN4TVdKdGJEQmxVemxvV1ROU2NHSXlOWG9LVEROS01XSnVUWFpOZWtWNFRVUm5lVTlVWjNkT1JGVjJXVmhTTUZwWE1YZGtTRTEyVFZSQlYwSm5iM0pDWjBWRlFWbFBMMDFCUlZkQ1FXZE5RbTVDTVFwWmJYaHdXWHBDUjBKbmIzSkNaMFZGUVZsUEwwMUJSVmxDUkdkTlRtNUtiR05IT0RaaFNGWnVXakpzZFZveVdtaFpNbFYyWVRKV2VXSnRWbk5qZVRGcUNtSXlNWFJrVnpWd1pFaHJObU50Vm0xUGJrcHNXbTVOZG1GSFZtaGFTRTEyWWxkR2NHSnFRMEpwWjFsTFMzZFpRa0pCU0ZkbFVVbEZRV2RTT0VKSWIwRUtaVUZDTWtGT01EbE5SM0pIZUhoRmVWbDRhMlZJU214dVRuZExhVk5zTmpRemFubDBMelJsUzJOdlFYWkxaVFpQUVVGQlFtNDVaR3BLYWxGQlFVRlJSQXBCUldOM1VsRkphRUZKU1ZkRFdYaFhLM0pKTm1GaFRXazVTR2RFTWtSc1pWbFNOa29yUmpaWmNVdFlWWGhWZGpSYU5FZHRRV2xCZVdjNVdFRlJRMmxDQ2pWc1NsRnJaVmRPVjIxbkwwcFFSSFptVDFWTlIyeEtWbEZHWkU5d2FsZ3ZZbnBCUzBKblozRm9hMnBQVUZGUlJFRjNUbTlCUkVKc1FXcEJha0UzUWpjS1RFOTRXWFJqTjA1R01EUTViMUEyVVc4NU56VmhNa0UxZWxaNVZTOUNWM1ZEVDFGdmRpdDRZM2MxZWtSc2FWaG9RMWRZVDB4T1Z6SkNia0ZEVFZGRU1BcElNVEZFZFVwRE9WRllkMUZPYlVoM2FpdEJNamxuTDB4dVpFNVFhMnBXT1VGSmVVSnhObWgzVkdaWFNVVkZSRFpCYTNCcWJYVlBVMnRpVkhKdE1rRTlDaTB0TFMwdFJVNUVJRU5GVWxSSlJrbERRVlJGTFMwdExTMEsifX19fQ=="}], "timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyzADAgEAMIICwgYJKoZIhvcNAQcCoIICszCCAq8CAQMxDTALBglghkgBZQMEAgEwgbgGCyqGSIb3DQEJEAEEoIGoBIGlMIGiAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQghTN3Etc/xMW2ECEnnJ77fF4BFTlIInKJA+klU1KR364CFQDI1qpdKNJ+eB43rDLpCBw+sGN+HxgPMjAyNjA4MDYxNDAzNDdaMAMCAQGgMqQwMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhoAAxggHcMIIB2AIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MDgwNjE0MDM0N1owLwYJKoZIhvcNAQkEMSIEIMpfp637Nc+LAhkPFU6iox6d4QDZrv1y+2irknjjsgXOMIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCCF+Se8B6tiysO0Q1bBDvyBssaIP9p6uebYcNnROs0FtzBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQ6E1QvDJBh7rzBQy/Lio6LKiOLDDAKBggqhkjOPQQDAgRoMGYCMQC542sKD2Td6CYDzDxI/dgV+8SVjUZVYPo4mJTdgP6Hd7R+QAV73XhuCT3ZHaX+dO8CMQDrfFq1+W81IP5G6WQG9G5xqXqyDbIUsSmlZJHMsPkiK4+y30rW0rYtVZk8XTacep4="}]}}, "messageSignature":{"messageDigest":{"algorithm":"SHA2_256", "digest":"nbHLGKPbMel6UlMvP3Ew1dEWGrNjdvzlBO5/EGDtGcg="}, "signature":"MEQCIHt5x/7WAsel2ijjIyyHl2rX/S+wSOcREpaH0jTcyJfRAiB9xK4DFPxHWd22Qdy2WJ6kx6gIFgpigcFs0YmZFKS0dQ=="}}
|
build/torch-stable-abi29-cu130-x86_64-linux/nvfp4_gemm/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import ctypes
|
| 2 |
+
import importlib.util
|
| 3 |
+
import sys
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from types import ModuleType
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def _import_from_path(file_path: Path) -> ModuleType:
|
| 9 |
+
# We cannot use the module name as-is, after adding it to `sys.modules`,
|
| 10 |
+
# it would also be used for other imports. So, we make a module name that
|
| 11 |
+
# depends on the path for it to be unique using the hex-encoded hash of
|
| 12 |
+
# the path.
|
| 13 |
+
path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
|
| 14 |
+
module_name = path_hash
|
| 15 |
+
spec = importlib.util.spec_from_file_location(module_name, file_path)
|
| 16 |
+
if spec is None:
|
| 17 |
+
raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
|
| 18 |
+
module = importlib.util.module_from_spec(spec)
|
| 19 |
+
if module is None:
|
| 20 |
+
raise ImportError(f"Cannot load module {module_name} from spec")
|
| 21 |
+
sys.modules[module_name] = module
|
| 22 |
+
spec.loader.exec_module(module) # type: ignore
|
| 23 |
+
return module
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
|
build/torch-stable-abi29-cu132-x86_64-linux/__init__.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from . import layers
|
| 2 |
+
from .layers import fuse_decode_projections
|
| 3 |
+
from .functional import gemm, gemm_swiglu
|
| 4 |
+
from ._pack import (
|
| 5 |
+
PackedWeight,
|
| 6 |
+
global_scale_for,
|
| 7 |
+
pack,
|
| 8 |
+
pack_swiglu,
|
| 9 |
+
quantize_reference,
|
| 10 |
+
swizzled_sf_shape,
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
__all__ = [
|
| 14 |
+
"PackedWeight",
|
| 15 |
+
"pack",
|
| 16 |
+
"pack_swiglu",
|
| 17 |
+
"quantize_reference",
|
| 18 |
+
"global_scale_for",
|
| 19 |
+
"swizzled_sf_shape",
|
| 20 |
+
"gemm",
|
| 21 |
+
"gemm_swiglu",
|
| 22 |
+
"layers",
|
| 23 |
+
"fuse_decode_projections",
|
| 24 |
+
]
|
build/torch-stable-abi29-cu132-x86_64-linux/_nvfp4_gemm_cuda_9c5a0e3.abi3.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d789bb047d295c5147d5865809881daf3aa4384e30addbc61d5b2f4e03b23c4e
|
| 3 |
+
size 3260632
|
build/torch-stable-abi29-cu132-x86_64-linux/_ops.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from . import _nvfp4_gemm_cuda_9c5a0e3
|
| 3 |
+
ops = torch.ops._nvfp4_gemm_cuda_9c5a0e3
|
| 4 |
+
|
| 5 |
+
def add_op_namespace_prefix(op_name: str):
|
| 6 |
+
"""
|
| 7 |
+
Prefix op by namespace.
|
| 8 |
+
"""
|
| 9 |
+
return f"_nvfp4_gemm_cuda_9c5a0e3::{op_name}"
|
build/torch-stable-abi29-cu132-x86_64-linux/_pack.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dataclasses import dataclass
|
| 2 |
+
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
from ._ops import ops
|
| 6 |
+
|
| 7 |
+
FLOAT8_E4M3_MAX = 448.0
|
| 8 |
+
FLOAT4_E2M1_MAX = 6.0
|
| 9 |
+
SF_VEC_SIZE = 16 # elements sharing one FP8 scale
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def _round_up(x: int, m: int) -> int:
|
| 13 |
+
return (x + m - 1) // m * m
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def swizzled_sf_shape(rows: int, cols: int) -> tuple[int, int]:
|
| 17 |
+
"""Shape of the swizzled scale-factor tensor (dtype int32) produced by
|
| 18 |
+
`scaled_fp4_quant(..., is_sf_swizzled_layout=True)` for a [rows, cols]
|
| 19 |
+
input. Mirrors `computeSwizzledSFShape` in nvfp4_utils.cuh: 128-row tiles,
|
| 20 |
+
4 FP8 scales packed per int32 column."""
|
| 21 |
+
return _round_up(rows, 128), _round_up(cols // SF_VEC_SIZE, 4) // 4
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def global_scale_for(w: torch.Tensor) -> torch.Tensor:
|
| 25 |
+
"""Per-tensor second-level scale: FP8_MAX * FP4_MAX / amax."""
|
| 26 |
+
amax = w.abs().amax().to(torch.float32)
|
| 27 |
+
return (FLOAT8_E4M3_MAX * FLOAT4_E2M1_MAX / amax.clamp(min=1e-12)).reshape(1)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
@dataclass
|
| 31 |
+
class PackedWeight:
|
| 32 |
+
"""NVFP4 representation of a bf16 matrix [n, k]."""
|
| 33 |
+
|
| 34 |
+
qweight: torch.Tensor # uint8 [n, k/2], two e2m1 values per byte
|
| 35 |
+
sf: torch.Tensor # int32, swizzled FP8-E4M3 block scales
|
| 36 |
+
global_scale: torch.Tensor # fp32 [1]
|
| 37 |
+
n: int
|
| 38 |
+
k: int
|
| 39 |
+
swiglu: bool = False
|
| 40 |
+
# uint8 [n, k/16] row-major FP8-E4M3 block scales, consumed by the W4A16
|
| 41 |
+
# GEMV decode path (None when only the swizzled layout is available).
|
| 42 |
+
sf_rowmajor: torch.Tensor | None = None
|
| 43 |
+
|
| 44 |
+
def to(self, device) -> "PackedWeight":
|
| 45 |
+
return PackedWeight(
|
| 46 |
+
qweight=self.qweight.to(device),
|
| 47 |
+
sf=self.sf.to(device),
|
| 48 |
+
global_scale=self.global_scale.to(device),
|
| 49 |
+
n=self.n,
|
| 50 |
+
k=self.k,
|
| 51 |
+
swiglu=self.swiglu,
|
| 52 |
+
sf_rowmajor=(
|
| 53 |
+
None if self.sf_rowmajor is None else self.sf_rowmajor.to(device)
|
| 54 |
+
),
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def pack(
|
| 59 |
+
w: torch.Tensor, device: str | torch.device = "cuda", swiglu: bool = False
|
| 60 |
+
) -> PackedWeight:
|
| 61 |
+
"""Quantize a bf16/fp16 matrix [n, k] to NVFP4 (requires sm100+)."""
|
| 62 |
+
if w.dim() != 2 or not w.is_floating_point():
|
| 63 |
+
raise ValueError("pack() expects a 2-D floating-point weight")
|
| 64 |
+
n, k = w.shape
|
| 65 |
+
if k % SF_VEC_SIZE != 0:
|
| 66 |
+
raise ValueError(f"in_features must be a multiple of {SF_VEC_SIZE}, got {k}")
|
| 67 |
+
wd = w.detach().to(device, torch.bfloat16).contiguous()
|
| 68 |
+
gs = global_scale_for(wd).to(device)
|
| 69 |
+
qweight, sf = ops.scaled_fp4_quant(wd, gs, True)
|
| 70 |
+
# Row-major scales for the W4A16 GEMV decode path; the qweight output is
|
| 71 |
+
# identical to the swizzled call's, so it is discarded.
|
| 72 |
+
_, sf_rowmajor = ops.scaled_fp4_quant(wd, gs, False)
|
| 73 |
+
return PackedWeight(
|
| 74 |
+
qweight=qweight,
|
| 75 |
+
sf=sf,
|
| 76 |
+
global_scale=gs,
|
| 77 |
+
n=n,
|
| 78 |
+
k=k,
|
| 79 |
+
swiglu=swiglu,
|
| 80 |
+
sf_rowmajor=sf_rowmajor,
|
| 81 |
+
)
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def pack_swiglu(
|
| 85 |
+
w_gate: torch.Tensor, w_up: torch.Tensor, device: str | torch.device = "cuda"
|
| 86 |
+
) -> PackedWeight:
|
| 87 |
+
"""Pack gate and up projections [n, k] as one [2n, k] matrix; the GEMM
|
| 88 |
+
output has gate values in columns [0, n) and up in [n, 2n)."""
|
| 89 |
+
if w_gate.shape != w_up.shape:
|
| 90 |
+
raise ValueError("gate and up matrices must have the same shape")
|
| 91 |
+
return pack(torch.cat([w_gate, w_up], dim=0), device=device, swiglu=True)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def quantize_reference(w: torch.Tensor) -> torch.Tensor:
|
| 95 |
+
"""Pure-torch NVFP4 emulation (no GPU kernel): quantize + dequantize to
|
| 96 |
+
the same numerics the kernel produces, for tests and quality analysis."""
|
| 97 |
+
orig_dtype = w.dtype
|
| 98 |
+
wf = w.float()
|
| 99 |
+
gs = global_scale_for(wf) # fp8_max*fp4_max/amax
|
| 100 |
+
n, k = wf.shape
|
| 101 |
+
g = wf.reshape(n, k // SF_VEC_SIZE, SF_VEC_SIZE)
|
| 102 |
+
# Block scale: amax/FP4_MAX * global_scale, stored in FP8-E4M3.
|
| 103 |
+
block_amax = g.abs().amax(-1, keepdim=True)
|
| 104 |
+
sf = (block_amax / FLOAT4_E2M1_MAX) * gs
|
| 105 |
+
sf = sf.to(torch.float8_e4m3fn).float().clamp(min=1e-12)
|
| 106 |
+
scaled = g * (gs / sf)
|
| 107 |
+
# e2m1 grid: {0, .5, 1, 1.5, 2, 3, 4, 6} with signs.
|
| 108 |
+
grid = torch.tensor([0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0])
|
| 109 |
+
q = grid[(scaled.abs().unsqueeze(-1) - grid).abs().argmin(-1)] * scaled.sign()
|
| 110 |
+
return (q * sf / gs).reshape(n, k).to(orig_dtype)
|
build/torch-stable-abi29-cu132-x86_64-linux/functional.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
|
| 3 |
+
from ._ops import add_op_namespace_prefix, ops
|
| 4 |
+
from ._pack import FLOAT4_E2M1_MAX, FLOAT8_E4M3_MAX, PackedWeight, swizzled_sf_shape
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
@torch.library.register_fake(add_op_namespace_prefix("scaled_fp4_quant"))
|
| 8 |
+
def _quant_fake(input, input_global_scale, is_sf_swizzled_layout):
|
| 9 |
+
n = input.size(-1)
|
| 10 |
+
m = input.numel() // n
|
| 11 |
+
out = input.new_empty((m, n // 2), dtype=torch.uint8)
|
| 12 |
+
if is_sf_swizzled_layout:
|
| 13 |
+
sf_m, sf_n = swizzled_sf_shape(m, n)
|
| 14 |
+
sf = input.new_empty((sf_m, sf_n), dtype=torch.int32)
|
| 15 |
+
else:
|
| 16 |
+
sf = input.new_empty((m, n // 16), dtype=torch.uint8)
|
| 17 |
+
return out, sf
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
@torch.library.register_fake(add_op_namespace_prefix("cutlass_scaled_fp4_mm"))
|
| 21 |
+
def _mm_fake(a, b, a_sf, b_sf, alpha):
|
| 22 |
+
return a.new_empty((a.size(0), b.size(0)), dtype=torch.bfloat16)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
@torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemv"))
|
| 26 |
+
def _gemv_fake(a, b, b_sf, alpha):
|
| 27 |
+
return a.new_empty((a.size(0), b.size(0)), dtype=torch.bfloat16)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
@torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemv_swiglu"))
|
| 31 |
+
def _gemv_swiglu_fake(a, b, b_sf, alpha):
|
| 32 |
+
return a.new_empty((a.size(0), b.size(0) // 2), dtype=torch.bfloat16)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
@torch.library.register_fake(add_op_namespace_prefix("nvfp4_gemv_gated"))
|
| 36 |
+
def _gemv_gated_fake(a, g, b, b_sf, alpha):
|
| 37 |
+
return a.new_empty((a.size(0), b.size(0)), dtype=torch.bfloat16)
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def _as_fp8(sf: torch.Tensor) -> torch.Tensor:
|
| 41 |
+
return sf.view(torch.float8_e4m3fn) if sf.dtype == torch.int32 else sf
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def gemm(pw: PackedWeight, x: torch.Tensor) -> torch.Tensor:
|
| 45 |
+
"""y[..., n] = x[..., k] @ W.T with dynamic NVFP4 activation quantization
|
| 46 |
+
(W4A4 on the Blackwell block-scaled tensor cores)."""
|
| 47 |
+
if x.shape[-1] != pw.k:
|
| 48 |
+
raise ValueError(f"expected {pw.k} input features, got {x.shape[-1]}")
|
| 49 |
+
x2 = x.reshape(-1, pw.k)
|
| 50 |
+
if not x2.is_contiguous():
|
| 51 |
+
x2 = x2.contiguous()
|
| 52 |
+
# Decode path: W4A16 GEMV keeps activations in bf16 (no activation
|
| 53 |
+
# quantization). The kernel re-reads the weight per output row, so it is
|
| 54 |
+
# only worthwhile for tiny m; prefill stays on the W4A4 CUTLASS path.
|
| 55 |
+
if x2.size(0) <= 2 and getattr(pw, "sf_rowmajor", None) is not None:
|
| 56 |
+
alpha = (1.0 / pw.global_scale).to(torch.float32).reshape(1)
|
| 57 |
+
y = ops.nvfp4_gemv(x2.to(torch.bfloat16), pw.qweight, pw.sf_rowmajor, alpha)
|
| 58 |
+
return y.reshape(*x.shape[:-1], pw.n)
|
| 59 |
+
a_amax = x2.abs().amax().to(torch.float32)
|
| 60 |
+
a_gs = (FLOAT8_E4M3_MAX * FLOAT4_E2M1_MAX / a_amax.clamp(min=1e-12)).reshape(1)
|
| 61 |
+
aq, a_sf = ops.scaled_fp4_quant(x2.to(torch.bfloat16), a_gs, True)
|
| 62 |
+
alpha = (1.0 / (a_gs * pw.global_scale)).to(torch.float32)
|
| 63 |
+
# The quant op returns swizzled scales packed 4-per-int32; the GEMM takes
|
| 64 |
+
# the same bytes typed as fp8-e4m3.
|
| 65 |
+
y = ops.cutlass_scaled_fp4_mm(aq, pw.qweight, _as_fp8(a_sf), _as_fp8(pw.sf), alpha)
|
| 66 |
+
return y.reshape(*x.shape[:-1], pw.n)
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def gemm_swiglu(pw: PackedWeight, x: torch.Tensor) -> torch.Tensor:
|
| 70 |
+
"""silu(x @ W_gate.T) * (x @ W_up.T) for a SwiGLU-packed matrix."""
|
| 71 |
+
if not pw.swiglu:
|
| 72 |
+
raise ValueError("packed matrix was not packed with pack_swiglu")
|
| 73 |
+
y = gemm(pw, x)
|
| 74 |
+
half = pw.n // 2
|
| 75 |
+
return torch.nn.functional.silu(y[..., :half]) * y[..., half:]
|
build/torch-stable-abi29-cu132-x86_64-linux/layers.py
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
|
| 4 |
+
from .functional import gemm
|
| 5 |
+
from ._ops import ops
|
| 6 |
+
from ._pack import PackedWeight
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class NVFP4Linear(nn.Module):
|
| 10 |
+
can_torch_compile = True
|
| 11 |
+
has_backward = False
|
| 12 |
+
|
| 13 |
+
def forward(self, x):
|
| 14 |
+
pw = PackedWeight(
|
| 15 |
+
qweight=self.weight,
|
| 16 |
+
sf=self.weight_sf,
|
| 17 |
+
global_scale=self.weight_global_scale,
|
| 18 |
+
n=self.out_features,
|
| 19 |
+
k=self.in_features,
|
| 20 |
+
sf_rowmajor=getattr(self, "weight_sf_rowmajor", None),
|
| 21 |
+
)
|
| 22 |
+
return gemm(pw, x)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def _ntokens(x):
|
| 26 |
+
return x.numel() // x.shape[-1]
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def _fused_gemv(module, x):
|
| 30 |
+
return ops.nvfp4_gemv(
|
| 31 |
+
x.reshape(-1, x.shape[-1]).to(torch.bfloat16),
|
| 32 |
+
module.nvfp4_fused_qweight,
|
| 33 |
+
module.nvfp4_fused_sf,
|
| 34 |
+
module.nvfp4_fused_alpha,
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class NVFP4FusedSwiGLUMLP(nn.Module):
|
| 39 |
+
can_torch_compile = True
|
| 40 |
+
has_backward = False
|
| 41 |
+
|
| 42 |
+
def forward(self, x):
|
| 43 |
+
if _ntokens(x) <= 2 and hasattr(self, "nvfp4_fused_qweight"):
|
| 44 |
+
x2 = x.reshape(-1, x.shape[-1]).to(torch.bfloat16)
|
| 45 |
+
h = ops.nvfp4_gemv_swiglu(
|
| 46 |
+
x2,
|
| 47 |
+
self.nvfp4_fused_qweight,
|
| 48 |
+
self.nvfp4_fused_sf,
|
| 49 |
+
self.nvfp4_fused_alpha,
|
| 50 |
+
)
|
| 51 |
+
return self.down_proj(h.reshape(*x.shape[:-1], -1))
|
| 52 |
+
return self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class NVFP4GatedAttention(nn.Module):
|
| 56 |
+
can_torch_compile = True
|
| 57 |
+
has_backward = False
|
| 58 |
+
|
| 59 |
+
def forward(
|
| 60 |
+
self,
|
| 61 |
+
hidden_states,
|
| 62 |
+
position_embeddings=None,
|
| 63 |
+
attention_mask=None,
|
| 64 |
+
past_key_values=None,
|
| 65 |
+
**kwargs,
|
| 66 |
+
):
|
| 67 |
+
from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS
|
| 68 |
+
|
| 69 |
+
input_shape = hidden_states.shape[:-1]
|
| 70 |
+
hidden_shape = (*input_shape, -1, self.head_dim)
|
| 71 |
+
og = None
|
| 72 |
+
if _ntokens(hidden_states) <= 2 and hasattr(self, "nvfp4_fused_qweight"):
|
| 73 |
+
fused = _fused_gemv(self, hidden_states)
|
| 74 |
+
q, k, v, *rest = torch.split(fused, self.nvfp4_fused_splits, dim=-1)
|
| 75 |
+
og = rest[0] if rest else None
|
| 76 |
+
else:
|
| 77 |
+
q = self.q_proj(hidden_states)
|
| 78 |
+
k = self.k_proj(hidden_states)
|
| 79 |
+
v = self.v_proj(hidden_states)
|
| 80 |
+
query_states = q.reshape(hidden_shape).transpose(1, 2)
|
| 81 |
+
key_states = k.reshape(hidden_shape).transpose(1, 2)
|
| 82 |
+
value_states = v.reshape(hidden_shape).transpose(1, 2)
|
| 83 |
+
|
| 84 |
+
norm = getattr(self, "qk_norm", None)
|
| 85 |
+
if norm is not None:
|
| 86 |
+
query_states = norm(query_states) * getattr(self, "qk_scale_factor", 1.0)
|
| 87 |
+
key_states = norm(key_states)
|
| 88 |
+
|
| 89 |
+
if position_embeddings is not None:
|
| 90 |
+
cos, sin = position_embeddings
|
| 91 |
+
query_states, key_states = self.nvfp4_rope(
|
| 92 |
+
query_states, key_states, cos, sin
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
if past_key_values is not None:
|
| 96 |
+
key_states, value_states = past_key_values.update(
|
| 97 |
+
key_states, value_states, self.layer_idx
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
attention_interface = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 101 |
+
self.config._attn_implementation, self.nvfp4_eager
|
| 102 |
+
)
|
| 103 |
+
attn_output, attn_weights = attention_interface(
|
| 104 |
+
self,
|
| 105 |
+
query_states,
|
| 106 |
+
key_states,
|
| 107 |
+
value_states,
|
| 108 |
+
attention_mask,
|
| 109 |
+
dropout=self.attention_dropout if self.training else 0.0,
|
| 110 |
+
scaling=self.scaling,
|
| 111 |
+
sliding_window=getattr(self, "sliding_window", None),
|
| 112 |
+
**kwargs,
|
| 113 |
+
)
|
| 114 |
+
|
| 115 |
+
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
| 116 |
+
if og is None and getattr(self, "gate_proj", None) is not None:
|
| 117 |
+
og = self.gate_proj(hidden_states)
|
| 118 |
+
o = self.o_proj
|
| 119 |
+
if og is not None and _ntokens(attn_output) <= 2 and _has_nvfp4(o):
|
| 120 |
+
a2 = attn_output.reshape(-1, attn_output.shape[-1])
|
| 121 |
+
og2 = og.reshape(a2.shape).contiguous()
|
| 122 |
+
alpha = (1.0 / o.weight_global_scale.float()).reshape(1)
|
| 123 |
+
y = ops.nvfp4_gemv_gated(a2, og2, o.weight, o.weight_sf_rowmajor, alpha)
|
| 124 |
+
return y.reshape(*input_shape, -1), attn_weights
|
| 125 |
+
if og is not None:
|
| 126 |
+
attn_output = attn_output * torch.sigmoid(og.reshape(attn_output.shape))
|
| 127 |
+
return o(attn_output), attn_weights
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
def _has_nvfp4(m):
|
| 131 |
+
return m is not None and hasattr(m, "weight_sf_rowmajor")
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def _is_silu(act):
|
| 135 |
+
return isinstance(act, nn.SiLU) or type(act).__name__ == "SiLUActivation"
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def _attach_fused(module, mods):
|
| 139 |
+
# Keep a single packed allocation and expose row views back through the
|
| 140 |
+
# original projection modules. Previously fusion allocated concatenated
|
| 141 |
+
# weights while retaining an independent copy in every projection.
|
| 142 |
+
# Attention and SwiGLU use row-concatenated storage; the latter is handled
|
| 143 |
+
# by the GEMV kernel using the gate/up half offset.
|
| 144 |
+
fused_qweight = torch.cat([m.weight for m in mods], 0).contiguous()
|
| 145 |
+
fused_sf = torch.cat([m.weight_sf_rowmajor for m in mods], 0).contiguous()
|
| 146 |
+
module.nvfp4_fused_qweight = fused_qweight
|
| 147 |
+
module.nvfp4_fused_sf = fused_sf
|
| 148 |
+
module.nvfp4_fused_alpha = torch.cat(
|
| 149 |
+
[
|
| 150 |
+
(1.0 / m.weight_global_scale.float())
|
| 151 |
+
.reshape(1)
|
| 152 |
+
.expand(m.out_features)
|
| 153 |
+
.contiguous()
|
| 154 |
+
for m in mods
|
| 155 |
+
]
|
| 156 |
+
)
|
| 157 |
+
module.nvfp4_fused_splits = [m.out_features for m in mods]
|
| 158 |
+
|
| 159 |
+
offset = 0
|
| 160 |
+
for m in mods:
|
| 161 |
+
end = offset + m.out_features
|
| 162 |
+
m.weight = fused_qweight[offset:end]
|
| 163 |
+
m.weight_sf_rowmajor = fused_sf[offset:end]
|
| 164 |
+
offset = end
|
| 165 |
+
|
| 166 |
+
|
| 167 |
+
def _capture_helpers(cls, rope_fn):
|
| 168 |
+
if getattr(cls, "nvfp4_eager", None) is not None:
|
| 169 |
+
return
|
| 170 |
+
fwd = cls.forward
|
| 171 |
+
names = ("apply_rotary_pos_emb_interleave", "apply_rotary_pos_emb")
|
| 172 |
+
rope = rope_fn or next(
|
| 173 |
+
(fwd.__globals__[n] for n in names if n in fwd.__code__.co_names), None
|
| 174 |
+
)
|
| 175 |
+
cls.nvfp4_rope = staticmethod(rope) if rope is not None else None
|
| 176 |
+
cls.nvfp4_eager = staticmethod(fwd.__globals__["eager_attention_forward"])
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
def _mark(cls, layer_name):
|
| 180 |
+
if getattr(cls, "kernel_layer_name", None) is not None:
|
| 181 |
+
return
|
| 182 |
+
try:
|
| 183 |
+
from kernels import use_kernel_forward_from_hub
|
| 184 |
+
|
| 185 |
+
use_kernel_forward_from_hub(layer_name)(cls)
|
| 186 |
+
except Exception:
|
| 187 |
+
cls.kernel_layer_name = layer_name
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
def fuse_decode_projections(model, rope_fn=None):
|
| 191 |
+
n = 0
|
| 192 |
+
for mod in model.modules():
|
| 193 |
+
qkv = [getattr(mod, p, None) for p in ("q_proj", "k_proj", "v_proj")]
|
| 194 |
+
if (
|
| 195 |
+
all(_has_nvfp4(p) for p in qkv)
|
| 196 |
+
and hasattr(mod, "o_proj")
|
| 197 |
+
and hasattr(mod, "layer_idx")
|
| 198 |
+
):
|
| 199 |
+
gate = getattr(mod, "gate_proj", None)
|
| 200 |
+
_attach_fused(mod, qkv + ([gate] if _has_nvfp4(gate) else []))
|
| 201 |
+
_capture_helpers(type(mod), rope_fn)
|
| 202 |
+
_mark(type(mod), "NVFP4GatedAttention")
|
| 203 |
+
n += 1
|
| 204 |
+
continue
|
| 205 |
+
gu = [getattr(mod, p, None) for p in ("gate_proj", "up_proj")]
|
| 206 |
+
if (
|
| 207 |
+
all(_has_nvfp4(p) for p in gu)
|
| 208 |
+
and hasattr(mod, "down_proj")
|
| 209 |
+
and _is_silu(getattr(mod, "act_fn", None))
|
| 210 |
+
and gu[0].out_features == gu[1].out_features
|
| 211 |
+
):
|
| 212 |
+
_attach_fused(mod, gu)
|
| 213 |
+
_mark(type(mod), "NVFP4SwiGLUMLP")
|
| 214 |
+
n += 1
|
| 215 |
+
return n
|
build/torch-stable-abi29-cu132-x86_64-linux/metadata.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "nvfp4-gemm",
|
| 3 |
+
"id": "_nvfp4_gemm_cuda_9c5a0e3",
|
| 4 |
+
"version": 1,
|
| 5 |
+
"license": "Apache-2.0",
|
| 6 |
+
"upstream": "git+https://github.com/vllm-project/vllm.git",
|
| 7 |
+
"python-depends": [],
|
| 8 |
+
"backend": {
|
| 9 |
+
"type": "cuda",
|
| 10 |
+
"archs": [
|
| 11 |
+
"10.0a",
|
| 12 |
+
"12.0a"
|
| 13 |
+
]
|
| 14 |
+
},
|
| 15 |
+
"digest": {
|
| 16 |
+
"algorithm": "sha256",
|
| 17 |
+
"files": {
|
| 18 |
+
"__init__.py": "ARXik9k13ZmZ/1tDxHgH6bQyJ8Cn6wmCrz5WEM+DABI=",
|
| 19 |
+
"_nvfp4_gemm_cuda_9c5a0e3.abi3.so": "14m7BH0pXFFH1YZYCYgdrzqkOE4wrdvGHVsvTgOyPE4=",
|
| 20 |
+
"_ops.py": "+jBXp3Uoatvj6U0lcsYwN/3KdSd8+Aknhm5T+xbff6w=",
|
| 21 |
+
"_pack.py": "jATF2LhpSLUEiPWSrhsCWeyxIyn80CSy2QJNkKMADlc=",
|
| 22 |
+
"functional.py": "ZTd0hcUOkDdU9ZvpQMPC81KBP3FUvkmfZu7d7mhZRss=",
|
| 23 |
+
"layers.py": "asplwNUY3+drs57APjw3J9kFLtswK9YI0SxRVHZj2Hg=",
|
| 24 |
+
"nvfp4_gemm/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
|
| 25 |
+
}
|
| 26 |
+
},
|
| 27 |
+
"provenance": {
|
| 28 |
+
"kernel-builder": {
|
| 29 |
+
"version": "0.17.0-dev0",
|
| 30 |
+
"sha": "19aaa6421e674e9fecc352bbae6eab81d19a6bf4",
|
| 31 |
+
"dirty": false
|
| 32 |
+
},
|
| 33 |
+
"kernel": {
|
| 34 |
+
"sha": "9c5a0e35e9733ee93d458d2d4d5814f67d209d29",
|
| 35 |
+
"dirty": false
|
| 36 |
+
}
|
| 37 |
+
}
|
| 38 |
+
}
|
build/torch-stable-abi29-cu132-x86_64-linux/metadata.json.sigstore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial":{"certificate":{"rawBytes":"MIIHSzCCBtGgAwIBAgIUQP0jgzq6iUNWh+2Y8Rxg9VqrtCMwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwODA2MTQwMzQ3WhcNMjYwODA2MTQxMzQ3WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbvXQv6+bD792eCLro0ZEBoUesPS3o66yHG0PtgJa1NhBoB4yV2geGnvcXQLZq7PWvs5pl1I6ycA6O+pv3a0jKaOCBfAwggXsMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUcuoodiclwg80Xgmz2zHcxEaSRcMwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wawYDVR0RAQH/BGEwX4ZdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDkGCisGAQQBg78wAQEEK2h0dHBzOi8vdG9rZW4uYWN0aW9ucy5naXRodWJ1c2VyY29udGVudC5jb20wHwYKKwYBBAGDvzABAgQRd29ya2Zsb3dfZGlzcGF0Y2gwNgYKKwYBBAGDvzABAwQoOWM1YTBlMzVlOTczM2VlOTNkNDU4ZDJkNGQ1ODE0ZjY3ZDIwOWQyOTATBgorBgEEAYO/MAEEBAVCdWlsZDArBgorBgEEAYO/MAEFBB1odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eTAdBgorBgEEAYO/MAEGBA9yZWZzL2hlYWRzL21haW4wOwYKKwYBBAGDvzABCAQtDCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMG0GCisGAQQBg78wAQkEXwxdaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5Ly5naXRodWIvd29ya2Zsb3dzL2J1aWxkLnlhbWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wAQoEKgwoOWM1YTBlMzVlOTczM2VlOTNkNDU4ZDJkNGQ1ODE0ZjY3ZDIwOWQyOTAbBgorBgEEAYO/MAELBA0MC3NlbGYtaG9zdGVkMEAGCisGAQQBg78wAQwEMgwwaHR0cHM6Ly9naXRodWIuY29tL2h1Z2dpbmdmYWNlL2tlcm5lbHMtY29tbXVuaXR5MDgGCisGAQQBg78wAQ0EKgwoOWM1YTBlMzVlOTczM2VlOTNkNDU4ZDJkNGQ1ODE0ZjY3ZDIwOWQyOTAfBgorBgEEAYO/MAEOBBEMD3JlZnMvaGVhZHMvbWFpbjAaBgorBgEEAYO/MAEPBAwMCjEwNzE0NzU1MjkwLgYKKwYBBAGDvzABEAQgDB5odHRwczovL2dpdGh1Yi5jb20vaHVnZ2luZ2ZhY2UwGAYKKwYBBAGDvzABEQQKDAgyNTcyMDc0MzBtBgorBgEEAYO/MAESBF8MXWh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS8uZ2l0aHViL3dvcmtmbG93cy9idWlsZC55YW1sQHJlZnMvaGVhZHMvbWFpbjA4BgorBgEEAYO/MAETBCoMKDljNWEwZTM1ZTk3MzNlZTkzZDQ1OGQyZDRkNTgxNGY2N2QyMDlkMjkwIQYKKwYBBAGDvzABFAQTDBF3b3JrZmxvd19kaXNwYXRjaDBkBgorBgEEAYO/MAEVBFYMVGh0dHBzOi8vZ2l0aHViLmNvbS9odWdnaW5nZmFjZS9rZXJuZWxzLWNvbW11bml0eS9hY3Rpb25zL3J1bnMvMzExMDgyOTgwNDUvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzBGBgorBgEEAYO/MAEYBDgMNnJlcG86aHVnZ2luZ2ZhY2Uva2VybmVscy1jb21tdW5pdHk6cmVmOnJlZnMvaGVhZHMvbWFpbjCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABn9djKbEAAAQDAEcwRQIhAOsiNNSfv3dX77qcN9iuNZj2oTpkyRL3wAyNHTGKxZe0AiBP1JX+m9rtjPbYEXSF8Cw+hk5BrZ5fxzNiZC3TI9FfgjAKBggqhkjOPQQDAwNoADBlAjEA/s95wwFRDQUOX06PKVEt45K6RnhS+AUm70/LIXqbqE+4kFjW5ruFyV+potMxLYKYAjBaoT33gaX/2cnP/Es5mBs7UBabUm/CfFYL+CBf0OzFKMXsYn3Gb+VRfAghuXxY+qI="}, "tlogEntries":[{"logIndex":"2360822794", "logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion":{"kind":"hashedrekord", "version":"0.0.1"}, "integratedTime":"1786025028", "inclusionPromise":{"signedEntryTimestamp":"MEQCIAJ+mz7Vh4YuC2Ju2kJBDk/nOMGzpY13mQRZEPtOVyB7AiBjx8QlP9qfjGWQWmDYA/QtrrVlnlcIWuGfMXeOK4yAyA=="}, "inclusionProof":{"logIndex":"2238918532", "rootHash":"rKIuTXmGd55gfj4rnFlrOuOrqWBpfOkbhZyhvBNAvj0=", "treeSize":"2238918554", "hashes":["l1vm1EL7VhYR/fL9IVTYJcPVc+efJzqct14GrWlyXLg=", "0F/8qEd4yf19WRRy8re+mSmkmNm9rrWnZOhzgKScN2w=", "Jz+PRA4FGGCnAdj3jIZjiHxchfAsf0y3ZBZdscAIVkw=", "DwgeNpdx/Xl0foZN932HJNaNZGxS/ApVyicyhFgh/3A=", "Khbu+Fuzutx3ADkt7AeAP4aiISNWAcz/kswjB45B21c=", "5WcoMXSpzvnq4KWL+iZGwWkjGDYd22yUN5/2n1rJbDw=", "yqmsZOsG1fWCdReSoyBV2DCsoA3XKvTEPnOnexLwYnI=", "yOi1SZCAJyQeGFNfXEyJmZfgE/yHiViHJh7AkVStYx0=", "ZDDgBLJeZMIedbwsKMeIdE+rnhT6LFyxK01q4RQswB8=", "1QfEqQEF22LcM0N+z5i77k0Oy00Arz4yjX7D1LTJP34=", "tSch9ErXVKdLoCFPSZ8D8aLt8T+YHXh/0cV7rQ+HxWc=", "VN19Pd6HJSN2xUEEfXlAK+NBL7uztCXLEaUeuJxgAbY=", "2DzQwQqFGfdTX3BVYQkcDxiT/TBV7lnr+ya29yCNm+o=", "QVx27ou3XJyzOgzVsHRov+ie3M7wOfT492kpmkbAeBo=", "lLhES7her3Dzu/HSMpPVolTSfVQlKbD23EIsEwXq4V4=", "kVyfjHB6dSBvAqnJBVxvTpb/VPDK9zzq5/txahxnbhc=", "u23nWGlBSoQOMevXp72NpPaDjuN0qcB01i17Odcs3Wk=", "i5Zl8FZrDwxCDv2e2DNO2M8JvpR/c11ElvCZS53/teA=", "xH/DCseLHr9eKoYT8qsORZK7zVdEGYWHuVtsVrD95wY="], "checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n2238918554\nrKIuTXmGd55gfj4rnFlrOuOrqWBpfOkbhZyhvBNAvj0=\n\n— rekor.sigstore.dev wNI9ajBFAiEAmIz2SLnVdzVNEMYAlAzbQ2Qqy+ULNVITLFWfsOxRQvYCIE9KfpPwYh1cVJZGK92tvhqJWkRphkx2o0JBP8+RXV8g\n"}}, "canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIxNGUxZTJjODY3YzAyZDVlNGYyYTNjMmM2NjUyNzk3MTY1ZGJmMzlhODZmYTkwYzliNmQwOWZjYmQ1ZWRlZWVjIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUMrSVJ0ZituN080NFVLMkJONlkybk4xN2hnaUNwUHpIRm9taklEL0p0K1NnSWhBT3plcTBFRk1WRGJEYisvVFViT3pUQWdRWFhCQS8vUURYS2tVbDVBeENDOSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaFRla05EUW5SSFowRjNTVUpCWjBsVlVWQXdhbWQ2Y1RacFZVNVhhQ3N5V1RoU2VHYzVWbkZ5ZEVOTmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDlFUVRKTlZGRjNUWHBSTTFkb1kwNU5hbGwzVDBSQk1rMVVVWGhOZWxFelYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZpZGxoUmRqWXJZa1EzT1RKbFEweHliekJhUlVKdlZXVnpVRk16YnpZMmVVaEhNRkFLZEdkS1lURk9hRUp2UWpSNVZqSm5aVWR1ZG1OWVVVeGFjVGRRVjNaek5YQnNNVWsyZVdOQk5rOHJjSFl6WVRCcVMyRlBRMEptUVhkbloxaHpUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZqZFc5dkNtUnBZMngzWnpnd1dHZHRlako2U0dONFJXRlRVbU5OZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJGM1dVUldVakJTUVZGSUwwSkhSWGRZTkZwa1lVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKb01Wb3laSEJpYldSdFdWZE9iQXBNTW5Sc1kyMDFiR0pJVFhSWk1qbDBZbGhXZFdGWVVqVk1lVFZ1WVZoU2IyUlhTWFprTWpsNVlUSmFjMkl6WkhwTU1rb3hZVmQ0YTB4dWJHaGlWM2hCQ21OdFZtMWplVGx2V2xkR2EyTjVPWFJaVjJ4MVRVUnJSME5wYzBkQlVWRkNaemM0ZDBGUlJVVkxNbWd3WkVoQ2VrOXBPSFprUnpseVdsYzBkVmxYVGpBS1lWYzVkV041Tlc1aFdGSnZaRmRLTVdNeVZubFpNamwxWkVkV2RXUkROV3BpTWpCM1NIZFpTMHQzV1VKQ1FVZEVkbnBCUWtGblVWSmtNamw1WVRKYWN3cGlNMlJtV2tkc2VtTkhSakJaTW1kM1RtZFpTMHQzV1VKQ1FVZEVkbnBCUWtGM1VXOVBWMDB4V1ZSQ2JFMTZWbXhQVkdONlRUSldiRTlVVG10T1JGVTBDbHBFU210T1IxRXhUMFJGTUZwcVdUTmFSRWwzVDFkUmVVOVVRVlJDWjI5eVFtZEZSVUZaVHk5TlFVVkZRa0ZXUTJSWGJITmFSRUZ5UW1kdmNrSm5SVVVLUVZsUEwwMUJSVVpDUWpGdlpGZGtibUZYTlc1YWJVWnFXbE01Y2xwWVNuVmFWM2g2VEZkT2RtSlhNVEZpYld3d1pWUkJaRUpuYjNKQ1owVkZRVmxQTHdwTlFVVkhRa0U1ZVZwWFducE1NbWhzV1ZkU2Vrd3lNV2hoVnpSM1QzZFpTMHQzV1VKQ1FVZEVkbnBCUWtOQlVYUkVRM1J2WkVoU2QyTjZiM1pNTTFKMkNtRXlWblZNYlVacVpFZHNkbUp1VFhWYU1td3dZVWhXYVdSWVRteGpiVTUyWW01U2JHSnVVWFZaTWpsMFRVY3dSME5wYzBkQlVWRkNaemM0ZDBGUmEwVUtXSGQ0WkdGSVVqQmpTRTAyVEhrNWJtRllVbTlrVjBsMVdUSTVkRXd5YURGYU1tUndZbTFrYlZsWFRteE1NblJzWTIwMWJHSklUWFJaTWpsMFlsaFdkUXBoV0ZJMVRIazFibUZZVW05a1YwbDJaREk1ZVdFeVduTmlNMlI2VERKS01XRlhlR3RNYm14b1lsZDRRV050Vm0xamVUbHZXbGRHYTJONU9YUlpWMngxQ2sxRVowZERhWE5IUVZGUlFtYzNPSGRCVVc5RlMyZDNiMDlYVFRGWlZFSnNUWHBXYkU5VVkzcE5NbFpzVDFST2EwNUVWVFJhUkVwclRrZFJNVTlFUlRBS1dtcFpNMXBFU1hkUFYxRjVUMVJCWWtKbmIzSkNaMFZGUVZsUEwwMUJSVXhDUVRCTlF6Tk9iR0pIV1hSaFJ6bDZaRWRXYTAxRlFVZERhWE5IUVZGUlFncG5OemgzUVZGM1JVMW5kM2RoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NbWd4V2pKa2NHSnRaRzFaVjA1c1RESjBiR050Tld4aVNFMTBDbGt5T1hSaVdGWjFZVmhTTlUxRVowZERhWE5IUVZGUlFtYzNPSGRCVVRCRlMyZDNiMDlYVFRGWlZFSnNUWHBXYkU5VVkzcE5NbFpzVDFST2EwNUVWVFFLV2tSS2EwNUhVVEZQUkVVd1dtcFpNMXBFU1hkUFYxRjVUMVJCWmtKbmIzSkNaMFZGUVZsUEwwMUJSVTlDUWtWTlJETktiRnB1VFhaaFIxWm9Xa2hOZGdwaVYwWndZbXBCWVVKbmIzSkNaMFZGUVZsUEwwMUJSVkJDUVhkTlEycEZkMDU2UlRCT2VsVXhUV3ByZDB4bldVdExkMWxDUWtGSFJIWjZRVUpGUVZGbkNrUkNOVzlrU0ZKM1kzcHZka3d5WkhCa1IyZ3hXV2sxYW1JeU1IWmhTRlp1V2pKc2RWb3lXbWhaTWxWM1IwRlpTMHQzV1VKQ1FVZEVkbnBCUWtWUlVVc0tSRUZuZVU1VVkzbE5SR013VFhwQ2RFSm5iM0pDWjBWRlFWbFBMMDFCUlZOQ1JqaE5XRmRvTUdSSVFucFBhVGgyV2pKc01HRklWbWxNYlU1MllsTTVid3BrVjJSdVlWYzFibHB0Um1wYVV6bHlXbGhLZFZwWGVIcE1WMDUyWWxjeE1XSnRiREJsVXpoMVdqSnNNR0ZJVm1sTU0yUjJZMjEwYldKSE9UTmplVGxwQ21SWGJITmFRelUxV1ZjeGMxRklTbXhhYmsxMllVZFdhRnBJVFhaaVYwWndZbXBCTkVKbmIzSkNaMFZGUVZsUEwwMUJSVlJDUTI5TlMwUnNhazVYUlhjS1dsUk5NVnBVYXpOTmVrNXNXbFJyZWxwRVVURlBSMUY1V2tSU2EwNVVaM2hPUjFreVRqSlJlVTFFYkd0TmFtdDNTVkZaUzB0M1dVSkNRVWRFZG5wQlFncEdRVkZVUkVKR00ySXpTbkphYlhoMlpERTVhMkZZVG5kWldGSnFZVVJDYTBKbmIzSkNaMFZGUVZsUEwwMUJSVlpDUmxsTlZrZG9NR1JJUW5wUGFUaDJDbG95YkRCaFNGWnBURzFPZG1KVE9XOWtWMlJ1WVZjMWJscHRSbXBhVXpseVdsaEtkVnBYZUhwTVYwNTJZbGN4TVdKdGJEQmxVemxvV1ROU2NHSXlOWG9LVEROS01XSnVUWFpOZWtWNFRVUm5lVTlVWjNkT1JGVjJXVmhTTUZwWE1YZGtTRTEyVFZSQlYwSm5iM0pDWjBWRlFWbFBMMDFCUlZkQ1FXZE5RbTVDTVFwWmJYaHdXWHBDUjBKbmIzSkNaMFZGUVZsUEwwMUJSVmxDUkdkTlRtNUtiR05IT0RaaFNGWnVXakpzZFZveVdtaFpNbFYyWVRKV2VXSnRWbk5qZVRGcUNtSXlNWFJrVnpWd1pFaHJObU50Vm0xUGJrcHNXbTVOZG1GSFZtaGFTRTEyWWxkR2NHSnFRMEpwWjFsTFMzZFpRa0pCU0ZkbFVVbEZRV2RTT0VKSWIwRUtaVUZDTWtGT01EbE5SM0pIZUhoRmVWbDRhMlZJU214dVRuZExhVk5zTmpRemFubDBMelJsUzJOdlFYWkxaVFpQUVVGQlFtNDVaR3BMWWtWQlFVRlJSQXBCUldOM1VsRkphRUZQYzJsT1RsTm1kak5rV0RjM2NXTk9PV2wxVGxwcU1tOVVjR3Q1VWt3emQwRjVUa2hVUjB0NFdtVXdRV2xDVURGS1dDdHRPWEowQ21wUVlsbEZXRk5HT0VOM0syaHJOVUp5V2pWbWVIcE9hVnBETTFSSk9VWm1aMnBCUzBKblozRm9hMnBQVUZGUlJFRjNUbTlCUkVKc1FXcEZRUzl6T1RVS2QzZEdVa1JSVlU5WU1EWlFTMVpGZERRMVN6WlNibWhUSzBGVmJUY3dMMHhKV0hGaWNVVXJOR3RHYWxjMWNuVkdlVllyY0c5MFRYaE1XVXRaUVdwQ1lRcHZWRE16WjJGWUx6SmpibEF2UlhNMWJVSnpOMVZDWVdKVmJTOURaa1paVEN0RFFtWXdUM3BHUzAxWWMxbHVNMGRpSzFaU1prRm5hSFZZZUZrcmNVazlDaTB0TFMwdFJVNUVJRU5GVWxSSlJrbERRVlJGTFMwdExTMEsifX19fQ=="}], "timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIICyDADAgEAMIICvwYJKoZIhvcNAQcCoIICsDCCAqwCAQMxDTALBglghkgBZQMEAgEwgbcGCyqGSIb3DQEJEAEEoIGnBIGkMIGhAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgh4l2yHCu2Fcn5cUOXzkBeFDycvtXlAwWfstiCWJHOBICFCoS8RsGtrqrA0MYbJJ1ijGKLC3/GA8yMDI2MDgwNjE0MDM0OFowAwIBAaAypDAwLjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MRUwEwYDVQQDEwxzaWdzdG9yZS10c2GgADGCAdowggHWAgEBMFEwOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZAIUOhNULwyQYe68wUMvy4qOiyojiwwwCwYJYIZIAWUDBAIBoIH8MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjYwODA2MTQwMzQ4WjAvBgkqhkiG9w0BCQQxIgQg01rCf9QOSiyZ4ePyHpLBqsF0VteUJpog/dh5HI/aZF0wgY4GCyqGSIb3DQEJEAIvMX8wfTB7MHkEIIX5J7wHq2LKw7RDVsEO/IGyxog/2nq55thw2dE6zQW3MFUwPaQ7MDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAoGCCqGSM49BAMCBGYwZAIwPjTPW5DMjgqk0A64hqM6XisNWoNvg6jPTrOWBB56tPdRKkapJd0uAl8aFjYnhRM2AjBGOab1G98aPMpxMrVAJ60YS1Pf0MzpeZhaYTbUf/nREyNTRYeuZ9V30AkZlQ7CYnQ="}]}}, "messageSignature":{"messageDigest":{"algorithm":"SHA2_256", "digest":"FOHiyGfALV5PKjwsZlJ5cWXb85qG+pDJttCfy9Xt7uw="}, "signature":"MEYCIQC+IRtf+n7O44UK2BN6Y2nN17hgiCpPzHFomjID/Jt+SgIhAOzeq0EFMVDbDb+/TUbOzTAgQXXBA//QDXKkUl5AxCC9"}}
|
build/torch-stable-abi29-cu132-x86_64-linux/nvfp4_gemm/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import ctypes
|
| 2 |
+
import importlib.util
|
| 3 |
+
import sys
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from types import ModuleType
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def _import_from_path(file_path: Path) -> ModuleType:
|
| 9 |
+
# We cannot use the module name as-is, after adding it to `sys.modules`,
|
| 10 |
+
# it would also be used for other imports. So, we make a module name that
|
| 11 |
+
# depends on the path for it to be unique using the hex-encoded hash of
|
| 12 |
+
# the path.
|
| 13 |
+
path_hash = "{:x}".format(ctypes.c_size_t(hash(file_path.absolute())).value)
|
| 14 |
+
module_name = path_hash
|
| 15 |
+
spec = importlib.util.spec_from_file_location(module_name, file_path)
|
| 16 |
+
if spec is None:
|
| 17 |
+
raise ImportError(f"Cannot load spec for {module_name} from {file_path}")
|
| 18 |
+
module = importlib.util.module_from_spec(spec)
|
| 19 |
+
if module is None:
|
| 20 |
+
raise ImportError(f"Cannot load module {module_name} from spec")
|
| 21 |
+
sys.modules[module_name] = module
|
| 22 |
+
spec.loader.exec_module(module) # type: ignore
|
| 23 |
+
return module
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
globals().update(vars(_import_from_path(Path(__file__).parent.parent / "__init__.py")))
|