liangsu9988 commited on
Commit
e877859
·
verified ·
1 Parent(s): c3ea273

Add torch213-cxx11-cu130-aarch64-linux artifact

Browse files
build/torch213-cxx11-cu130-aarch64-linux/__init__.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FlashRT FP8 GEMM kernels."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import torch
6
+
7
+ from ._ops import add_op_namespace_prefix, ops
8
+
9
+
10
+ @torch.library.register_fake(add_op_namespace_prefix("fp8_linear_bf16"))
11
+ def _fp8_linear_bf16_fake(
12
+ input: torch.Tensor,
13
+ weight: torch.Tensor,
14
+ alpha: float,
15
+ variant: int,
16
+ out: torch.Tensor,
17
+ ) -> None:
18
+ if input.dim() != 2 or weight.dim() != 2:
19
+ raise RuntimeError("input and weight must be rank-2 tensors")
20
+ if out.shape != (input.shape[0], weight.shape[0]):
21
+ raise RuntimeError("out must have shape (input.shape[0], weight.shape[0])")
22
+ return None
23
+
24
+
25
+ @torch.library.register_fake(add_op_namespace_prefix("fp8_linear_residual_bf16"))
26
+ def _fp8_linear_residual_bf16_fake(
27
+ input: torch.Tensor,
28
+ weight: torch.Tensor,
29
+ alpha: float,
30
+ variant: int,
31
+ residual: torch.Tensor,
32
+ ) -> None:
33
+ if input.shape[0] != 1:
34
+ raise RuntimeError("residual path supports only M=1")
35
+ if residual.shape != (1, weight.shape[0]):
36
+ raise RuntimeError("residual must have shape (1, weight.shape[0])")
37
+ return None
38
+
39
+
40
+ @torch.library.register_fake(add_op_namespace_prefix("fp8_blockwise_linear_bf16"))
41
+ def _fp8_blockwise_linear_bf16_fake(
42
+ input: torch.Tensor,
43
+ weight: torch.Tensor,
44
+ input_scale: torch.Tensor,
45
+ weight_scale: torch.Tensor,
46
+ out: torch.Tensor,
47
+ ) -> None:
48
+ if input.dim() != 2 or weight.dim() != 2:
49
+ raise RuntimeError("input and weight must be rank-2 tensors")
50
+ m, k = input.shape
51
+ n = weight.shape[0]
52
+ if weight.shape[1] != k or n % 128 or k % 128:
53
+ raise RuntimeError("weight shape is invalid or N/K are not divisible by 128")
54
+ if input_scale.shape != (m, k // 128):
55
+ raise RuntimeError("input_scale must have shape (M, K / 128)")
56
+ if weight_scale.shape != (n // 128, k // 128):
57
+ raise RuntimeError("weight_scale must have shape (N / 128, K / 128)")
58
+ if out.shape != (m, n):
59
+ raise RuntimeError("out must have shape (M, N)")
60
+ return None
61
+
62
+
63
+ @torch.library.register_fake(
64
+ add_op_namespace_prefix("fp8_blockwise_swiglu_quantize_fp8")
65
+ )
66
+ def _fp8_blockwise_swiglu_quantize_fp8_fake(
67
+ input: torch.Tensor,
68
+ gate_up_weight: torch.Tensor,
69
+ input_scale: torch.Tensor,
70
+ gate_up_weight_scale: torch.Tensor,
71
+ output: torch.Tensor,
72
+ output_scale: torch.Tensor,
73
+ ) -> None:
74
+ m, k = input.shape
75
+ if gate_up_weight.dim() != 2 or gate_up_weight.shape[0] % 2:
76
+ raise RuntimeError("gate_up_weight must have shape (2*N, K)")
77
+ n = gate_up_weight.shape[0] // 2
78
+ if gate_up_weight.shape[1] != k or n % 128 or k % 128:
79
+ raise RuntimeError("gate_up_weight shape is invalid or N/K are not divisible by 128")
80
+ if input_scale.shape != (m, k // 128):
81
+ raise RuntimeError("input_scale must have shape (M, K/128)")
82
+ if gate_up_weight_scale.shape != (2 * n // 128, k // 128):
83
+ raise RuntimeError("gate_up_weight_scale must have shape (2*N/128, K/128)")
84
+ if output.shape != (m, n) or output_scale.shape != (m, n // 128):
85
+ raise RuntimeError("output buffers have invalid shapes")
86
+ return None
87
+
88
+
89
+ def select_fp8_linear_tile(m: int, n: int, k: int, variant: int = 0) -> str:
90
+ """Return the FlashRT tile selected by the public dispatcher."""
91
+
92
+ m = int(m)
93
+ n = int(n)
94
+ k = int(k)
95
+ variant = int(variant)
96
+ if m <= 0 or n <= 0 or k <= 0:
97
+ raise RuntimeError("m, n, and k must be positive")
98
+ if k % 32 != 0:
99
+ raise RuntimeError("k must be divisible by 32")
100
+ capability = torch.cuda.get_device_capability() if torch.cuda.is_available() else None
101
+ if capability == (11, 0):
102
+ forced = {1: "sm110_sq_bf16", 2: "sm110_t1_bf16", 3: "sm110_wide_bf16"}
103
+ if variant not in {0, *forced}:
104
+ raise RuntimeError("SM110 variant must be 0 (auto), 1 (Sq), 2 (T1), or 3 (Wide)")
105
+ if n % 16 or k % 16:
106
+ raise RuntimeError("SM110 requires n and k divisible by 16")
107
+ if variant:
108
+ return forced[variant]
109
+ if n >= 8 * k:
110
+ return "sm110_wide_bf16"
111
+ if m >= 128 and k >= 4 * n:
112
+ return "sm110_sq_bf16"
113
+ if n == k and m >= 512:
114
+ return "sm110_sq_bf16" if k <= 1024 else "sm110_wide_bf16"
115
+ if n == k and m >= 128:
116
+ return "sm110_wide_bf16"
117
+ return "sm110_t1_bf16"
118
+ if m == 1:
119
+ if variant == 4:
120
+ return "gemv_fp8_m1_w4"
121
+ if variant == 8:
122
+ return "gemv_fp8_m1_w8"
123
+ if variant == 16:
124
+ return "gemv_fp8_m1_w16"
125
+ if variant != 0:
126
+ raise RuntimeError("M=1 variant must be 0, 4, 8, or 16")
127
+ if n <= 2048:
128
+ return "gemv_fp8_m1_w4"
129
+ if n <= 8192:
130
+ return "gemv_fp8_m1_w8"
131
+ return "gemv_fp8_m1_w16"
132
+ if variant != 0:
133
+ raise RuntimeError("small-M dispatcher currently supports variant=0 only")
134
+ if m <= 16:
135
+ if k % 256 == 0:
136
+ return "ld_fp8_gemm_16x128x256_w4" if n % 128 == 0 else "ld_fp8_gemm_16x64x256_w4"
137
+ if n % 256 == 0:
138
+ return "ld_fp8_gemm_16x256x128_w8"
139
+ if n % 192 == 0:
140
+ return "ld_fp8_gemm_16x192x128_w4"
141
+ if n % 128 == 0:
142
+ return "ld_fp8_gemm_16x128x128_w4"
143
+ return "ld_fp8_gemm_16x64x128_w4"
144
+ if m <= 32:
145
+ if k % 256 == 0:
146
+ return "ld_fp8_gemm_32x128x256_w4" if n % 128 == 0 else "ld_fp8_gemm_32x64x256_w4"
147
+ if n % 192 == 0:
148
+ return "ld_fp8_gemm_32x192x128_w4"
149
+ if n % 128 == 0:
150
+ return "ld_fp8_gemm_32x128x128_w4"
151
+ return "ld_fp8_gemm_32x64x128_w4"
152
+ if m <= 64:
153
+ if k % 256 == 0:
154
+ return "ld_fp8_gemm_64x128x256_w4" if n % 128 == 0 else "ld_fp8_gemm_64x64x256_w4"
155
+ if n % 128 == 0:
156
+ return "ld_fp8_gemm_64x128x128_w4"
157
+ return "ld_fp8_gemm_64x64x128_w4"
158
+ raise RuntimeError("only M=1 decode or 2 <= M <= 64 small-M rows are supported")
159
+
160
+
161
+ def fp8_linear_bf16(
162
+ input: torch.Tensor,
163
+ weight: torch.Tensor,
164
+ alpha: float = 1.0,
165
+ out: torch.Tensor | None = None,
166
+ variant: int = 0,
167
+ ) -> torch.Tensor:
168
+ """Compute ``(input @ weight.T) * alpha`` with BF16 output.
169
+
170
+ ``input`` and ``weight`` must be FP8 E4M3 CUDA tensors with shapes
171
+ ``(M, K)`` and ``(N, K)``. ``alpha`` is a host float, normally the product
172
+ of static per-tensor input and weight scales. SM110 uses the production
173
+ CUTLASS Sq/T1/Wide dispatcher over full model row counts; SM120 uses the
174
+ hand-tuned M<=64 path.
175
+ """
176
+
177
+ if out is None:
178
+ out = torch.empty(
179
+ (input.shape[0], weight.shape[0]),
180
+ device=input.device,
181
+ dtype=torch.bfloat16,
182
+ )
183
+ ops.fp8_linear_bf16(input, weight, float(alpha), int(variant), out)
184
+ return out
185
+
186
+
187
+ def fp8_linear_residual_bf16(
188
+ input: torch.Tensor,
189
+ weight: torch.Tensor,
190
+ residual: torch.Tensor,
191
+ alpha: float = 1.0,
192
+ variant: int = 0,
193
+ ) -> torch.Tensor:
194
+ """In-place ``residual += (input @ weight.T) * alpha`` for M=1 decode."""
195
+
196
+ ops.fp8_linear_residual_bf16(input, weight, float(alpha), int(variant), residual)
197
+ return residual
198
+
199
+
200
+ def fp8_blockwise_linear_bf16(
201
+ input: torch.Tensor,
202
+ weight: torch.Tensor,
203
+ input_scale: torch.Tensor,
204
+ weight_scale: torch.Tensor,
205
+ out: torch.Tensor | None = None,
206
+ ) -> torch.Tensor:
207
+ """Block-128 scaled FP8 linear with BF16 output on SM89/SM120."""
208
+
209
+ if out is None:
210
+ out = torch.empty(
211
+ (input.shape[0], weight.shape[0]),
212
+ device=input.device,
213
+ dtype=torch.bfloat16,
214
+ )
215
+ ops.fp8_blockwise_linear_bf16(
216
+ input, weight, input_scale, weight_scale, out
217
+ )
218
+ return out
219
+
220
+
221
+ def fp8_blockwise_swiglu_quantize_fp8(
222
+ input: torch.Tensor,
223
+ gate_up_weight: torch.Tensor,
224
+ input_scale: torch.Tensor,
225
+ gate_up_weight_scale: torch.Tensor,
226
+ *,
227
+ output: torch.Tensor | None = None,
228
+ output_scale: torch.Tensor | None = None,
229
+ ) -> tuple[torch.Tensor, torch.Tensor]:
230
+ """SM89 block-128 FP8 gate/up GEMM + SiLU + FP8 requant producer."""
231
+
232
+ n = gate_up_weight.shape[0] // 2
233
+ if output is None:
234
+ output = torch.empty(
235
+ (input.shape[0], n), device=input.device, dtype=torch.float8_e4m3fn
236
+ )
237
+ if output_scale is None:
238
+ output_scale = torch.empty(
239
+ (input.shape[0], n // 128), device=input.device, dtype=torch.float32
240
+ )
241
+ ops.fp8_blockwise_swiglu_quantize_fp8(
242
+ input, gate_up_weight, input_scale, gate_up_weight_scale,
243
+ output, output_scale
244
+ )
245
+ return output, output_scale
246
+
247
+
248
+ __all__ = [
249
+ "fp8_linear_bf16",
250
+ "fp8_linear_residual_bf16",
251
+ "fp8_blockwise_linear_bf16",
252
+ "fp8_blockwise_swiglu_quantize_fp8",
253
+ "select_fp8_linear_tile",
254
+ ]
build/torch213-cxx11-cu130-aarch64-linux/_ops.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import torch
2
+ from . import fp8_gemm_source_test
3
+ ops = torch.ops.fp8_gemm_source_test
4
+
5
+ def add_op_namespace_prefix(op_name: str):
6
+ return f"fp8_gemm_source_test::{op_name}"
build/torch213-cxx11-cu130-aarch64-linux/fp8_gemm/__init__.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ctypes
2
+ import importlib.util
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ def _import_from_path(file_path: Path):
7
+ path_hash = '{:x}'.format(ctypes.c_size_t(hash(file_path.absolute())).value)
8
+ spec = importlib.util.spec_from_file_location(path_hash, file_path)
9
+ module = importlib.util.module_from_spec(spec)
10
+ sys.modules[path_hash] = module
11
+ spec.loader.exec_module(module)
12
+ return module
13
+
14
+ globals().update(vars(_import_from_path(Path(__file__).parent.parent / '__init__.py')))
build/torch213-cxx11-cu130-aarch64-linux/fp8_gemm_source_test.abi3.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6da6757d21dbf032ac9c79d54dceffafed47cbf28b392de481d03e6078f198a8
3
+ size 1893488
build/torch213-cxx11-cu130-aarch64-linux/metadata.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "fp8-gemm",
3
+ "id": "fp8_gemm_source_test",
4
+ "version": 1,
5
+ "license": "Apache-2.0",
6
+ "python-depends": [],
7
+ "backend": {
8
+ "type": "cuda",
9
+ "archs": [
10
+ "11.0a"
11
+ ]
12
+ },
13
+ "digest": {
14
+ "algorithm": "sha256",
15
+ "files": {
16
+ "__init__.py": "hKsdFER2ZmYz36/zz9LYE7ddsK/R1dprHJFx+9yBzks=",
17
+ "fp8_gemm_source_test.abi3.so": "baZ1fSHb8DKsnHnVTc7/r+1Hy/KLOS3kgdA+YHjxmKg=",
18
+ "_ops.py": "zi4cl9u1hlmXMSZ8ZPvvrFIj8y1rvp8y3OTUWOXsp84=",
19
+ "fp8_gemm/__init__.py": "v6p5XMfQzddhi1fLSAw4HX9CyS0rQsidvu9VsT01xi4="
20
+ }
21
+ },
22
+ "provenance": {
23
+ "kernel": {
24
+ "sha": "456d297",
25
+ "dirty": false
26
+ },
27
+ "validation": {
28
+ "torch": "2.13.0+cu130",
29
+ "cuda": "13.0"
30
+ }
31
+ }
32
+ }