orbitquant 0.2.2__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {orbitquant-0.2.2 → orbitquant-0.3.0}/PKG-INFO +21 -2
- {orbitquant-0.2.2 → orbitquant-0.3.0}/README.md +20 -1
- orbitquant-0.3.0/docs/assets/flux2-klein-9b-sdnq-vs-orbitquant.webp +0 -0
- orbitquant-0.3.0/docs/flux2-klein-9b-sdnq-vs-orbitquant.md +143 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/docs/kernel-audit.md +85 -31
- {orbitquant-0.2.2 → orbitquant-0.3.0}/docs/paper-methodology-audit.md +9 -3
- {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/CARD.md +37 -0
- orbitquant-0.3.0/native-kernels/orbitquant-packed-matmul/orbitquant_packed_matmul_cuda/packed_matmul.cu +1742 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/tests/test_packed_matmul.py +256 -34
- orbitquant-0.3.0/native-kernels/orbitquant-packed-matmul/torch-ext/orbitquant_packed_matmul/__init__.py +251 -0
- orbitquant-0.3.0/native-kernels/orbitquant-packed-matmul/torch-ext/torch_binding.cpp +42 -0
- orbitquant-0.3.0/native-kernels/orbitquant-packed-matmul/torch-ext/torch_binding.h +62 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/pyproject.toml +1 -1
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/__init__.py +1 -1
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/kernels/native_packed_matmul.py +125 -2
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/kernels/triton_cuda.py +535 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/layers.py +244 -10
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_ci.py +3 -1
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_documentation.py +8 -1
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_native_packed_matmul.py +39 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_orbit_linear.py +104 -18
- {orbitquant-0.2.2 → orbitquant-0.3.0}/uv.lock +1 -1
- orbitquant-0.2.2/native-kernels/orbitquant-packed-matmul/orbitquant_packed_matmul_cuda/packed_matmul.cu +0 -847
- orbitquant-0.2.2/native-kernels/orbitquant-packed-matmul/torch-ext/orbitquant_packed_matmul/__init__.py +0 -61
- orbitquant-0.2.2/native-kernels/orbitquant-packed-matmul/torch-ext/torch_binding.cpp +0 -18
- orbitquant-0.2.2/native-kernels/orbitquant-packed-matmul/torch-ext/torch_binding.h +0 -18
- {orbitquant-0.2.2 → orbitquant-0.3.0}/.github/workflows/ci.yml +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/.github/workflows/publish-pypi.yml +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/.gitignore +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/LICENSE +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/benchmarks/benchmark.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/build.toml +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/example.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/flake.lock +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/flake.nix +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/orbitquant_packed_matmul_metal/packed_matmul.metal +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/orbitquant_packed_matmul_metal/packed_matmul.mm +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/tests/__init__.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/run_cuda_kernel_checks.sh +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/run_hf_compat_checks.sh +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/run_mps_kernel_checks.sh +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/run_paper_methodology_checks.sh +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/runpod_ssh_health.sh +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/verify_hf_kernel_model_artifact.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/adaln.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/__init__.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/assets.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/benchmark.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/checksums.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/comparisons.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/loader.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/manifest.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/model_card.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/refresh.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/repair.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/validator.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/writer.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/benchmarks.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/cli/__init__.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/cli/main.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/codebooks/__init__.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/codebooks/lloyd_max.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/config.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/errors.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/__init__.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/assets.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/external_export.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/external_metrics.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/external_plan.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/metrics.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/native_plan.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/native_runner.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/native_settings.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/prompts.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/report.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/functional.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/hub.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/kernels/__init__.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/kernels/dispatch.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/kernels/mps.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/linear_adapters.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/modeling.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/packing/__init__.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/packing/bitpack.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/pipeline.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/__init__.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/flux.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/flux2.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/generic_dit.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/wan.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/z_image.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/quantizer.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/recipes.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/rotations/__init__.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/rotations/fwht.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/rotations/rpbh.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/transformers_ops.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_adaln_rtn.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_artifact_writer.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_benchmarks.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_bitpack.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_cli.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_cli_report.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_codebooks.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_config.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_diffusers_modelmixin_integration.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_distribution.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_eval_assets.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_eval_prompts.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_eval_report.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_external_eval_plan.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_external_export.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_hub.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_kernel_model_verifier.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_kernels.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_linear_adapters.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_manifest.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_model_card.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_model_quantization.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_native_kernel_package.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_native_runner.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_native_settings.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_optional_dependencies.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_paper_alignment.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_paper_methodology.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_pipeline_helpers.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_policies.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_prompt_jobs.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_prompt_selection.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_quantizer_adapter.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_rpbh.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_target_policies.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_transformers_pretrained_integration.py +0 -0
- {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_universal_transformers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: orbitquant
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Calibration-free OrbitQuant for transformer linear projections
|
|
5
5
|
Project-URL: Homepage, https://github.com/iamwavecut/OrbitQuant
|
|
6
6
|
Project-URL: Repository, https://github.com/iamwavecut/OrbitQuant
|
|
@@ -260,7 +260,7 @@ pipe = load_quantized_pipeline_from_artifact(
|
|
|
260
260
|
|
|
261
261
|
| Device | Dispatch |
|
|
262
262
|
| --- | --- |
|
|
263
|
-
| CUDA | Native packed
|
|
263
|
+
| CUDA | Native activation kernel plus packed W4A4 tensor-core path; native or Triton packed fallback |
|
|
264
264
|
| MPS | Native packed Metal package |
|
|
265
265
|
| CPU | PyTorch reference path |
|
|
266
266
|
|
|
@@ -274,6 +274,18 @@ Use the explicit reference path for compatibility or numerical debugging:
|
|
|
274
274
|
config = orbitquant.recipe("w4a4", runtime_mode="dequant_bf16")
|
|
275
275
|
```
|
|
276
276
|
|
|
277
|
+
On CUDA compute capability 8.0 or newer, the W4A4 fast path fuses token norm,
|
|
278
|
+
RPBH/FWHT, and codebook assignment in the native package, decodes only a bounded
|
|
279
|
+
output-channel chunk of packed weights to INT8, and uses the Torch CUTLASS
|
|
280
|
+
tensor-core matmul. It never materializes the full BF16/FP16 weight matrix.
|
|
281
|
+
The existing direct packed CUDA MMA kernel remains the fallback for compatible
|
|
282
|
+
W4A4 shapes when CUTLASS INT8 matmul is unavailable.
|
|
283
|
+
|
|
284
|
+
The optimized CUDA path maps the fixed Lloyd-Max centroids to a symmetric INT8
|
|
285
|
+
surrogate plus one scalar per codebook. Packed checkpoint indices and artifact
|
|
286
|
+
size are unchanged. Use `dequant_bf16` when exact Lloyd-Max centroid evaluation
|
|
287
|
+
is required.
|
|
288
|
+
|
|
277
289
|
Build the ABI3 native package locally without Kernel Hub:
|
|
278
290
|
|
|
279
291
|
```bash
|
|
@@ -282,6 +294,13 @@ nix --option sandbox relaxed run .#build-and-copy -L
|
|
|
282
294
|
export PYTHONPATH="$PWD/build/<matching-torch-backend-platform-variant>:$PYTHONPATH"
|
|
283
295
|
```
|
|
284
296
|
|
|
297
|
+
PyTorch 2.9 CUDA users can reduce allocator reservation during native diffusion
|
|
298
|
+
inference by setting the allocator before Python starts:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True python generate.py
|
|
302
|
+
```
|
|
303
|
+
|
|
285
304
|
The variant must match the Torch minor version, CUDA or Metal backend, C++ ABI,
|
|
286
305
|
architecture, and operating system. See
|
|
287
306
|
[`docs/kernel-audit.md`](docs/kernel-audit.md) for tested shapes, benchmark
|
|
@@ -216,7 +216,7 @@ pipe = load_quantized_pipeline_from_artifact(
|
|
|
216
216
|
|
|
217
217
|
| Device | Dispatch |
|
|
218
218
|
| --- | --- |
|
|
219
|
-
| CUDA | Native packed
|
|
219
|
+
| CUDA | Native activation kernel plus packed W4A4 tensor-core path; native or Triton packed fallback |
|
|
220
220
|
| MPS | Native packed Metal package |
|
|
221
221
|
| CPU | PyTorch reference path |
|
|
222
222
|
|
|
@@ -230,6 +230,18 @@ Use the explicit reference path for compatibility or numerical debugging:
|
|
|
230
230
|
config = orbitquant.recipe("w4a4", runtime_mode="dequant_bf16")
|
|
231
231
|
```
|
|
232
232
|
|
|
233
|
+
On CUDA compute capability 8.0 or newer, the W4A4 fast path fuses token norm,
|
|
234
|
+
RPBH/FWHT, and codebook assignment in the native package, decodes only a bounded
|
|
235
|
+
output-channel chunk of packed weights to INT8, and uses the Torch CUTLASS
|
|
236
|
+
tensor-core matmul. It never materializes the full BF16/FP16 weight matrix.
|
|
237
|
+
The existing direct packed CUDA MMA kernel remains the fallback for compatible
|
|
238
|
+
W4A4 shapes when CUTLASS INT8 matmul is unavailable.
|
|
239
|
+
|
|
240
|
+
The optimized CUDA path maps the fixed Lloyd-Max centroids to a symmetric INT8
|
|
241
|
+
surrogate plus one scalar per codebook. Packed checkpoint indices and artifact
|
|
242
|
+
size are unchanged. Use `dequant_bf16` when exact Lloyd-Max centroid evaluation
|
|
243
|
+
is required.
|
|
244
|
+
|
|
233
245
|
Build the ABI3 native package locally without Kernel Hub:
|
|
234
246
|
|
|
235
247
|
```bash
|
|
@@ -238,6 +250,13 @@ nix --option sandbox relaxed run .#build-and-copy -L
|
|
|
238
250
|
export PYTHONPATH="$PWD/build/<matching-torch-backend-platform-variant>:$PYTHONPATH"
|
|
239
251
|
```
|
|
240
252
|
|
|
253
|
+
PyTorch 2.9 CUDA users can reduce allocator reservation during native diffusion
|
|
254
|
+
inference by setting the allocator before Python starts:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True python generate.py
|
|
258
|
+
```
|
|
259
|
+
|
|
241
260
|
The variant must match the Torch minor version, CUDA or Metal backend, C++ ABI,
|
|
242
261
|
architecture, and operating system. See
|
|
243
262
|
[`docs/kernel-audit.md`](docs/kernel-audit.md) for tested shapes, benchmark
|
|
Binary file
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# FLUX.2 Klein 9B: OrbitQuant W4A4 vs SDNQ UINT4
|
|
2
|
+
|
|
3
|
+
This report compares OrbitQuant and SDNQ on the same FLUX.2 Klein 9B source,
|
|
4
|
+
prompts and generation settings. Runtime rows use the same L40S hardware and
|
|
5
|
+
software environment. It covers checkpoint size, load and generation latency,
|
|
6
|
+
VRAM, paired visual output and the measured OrbitQuant kernel path.
|
|
7
|
+
|
|
8
|
+
## Checkpoints
|
|
9
|
+
|
|
10
|
+
| Variant | Repository | Revision | Quantized components |
|
|
11
|
+
| --- | --- | --- | --- |
|
|
12
|
+
| BF16 | [`black-forest-labs/FLUX.2-klein-9B`](https://huggingface.co/black-forest-labs/FLUX.2-klein-9B) | `92196c8e11f7b6cf2b7493e037d8c5345c559216` | None |
|
|
13
|
+
| SDNQ UINT4 | [`WaveCut/FLUX.2-klein-9B-SDNQ-uint4-static`](https://huggingface.co/WaveCut/FLUX.2-klein-9B-SDNQ-uint4-static) | `ed71b3f19ce640e88b66a2a743aabb8a613adeac` | Transformer and Qwen3 text encoder |
|
|
14
|
+
| OrbitQuant W4A4 | [`WaveCut/FLUX.2-klein-9B-OrbitQuant-W4A4`](https://huggingface.co/WaveCut/FLUX.2-klein-9B-OrbitQuant-W4A4) | `ee3a38f7767ae199818d746c840be0f1837887bf` | Transformer and Qwen3 text encoder |
|
|
15
|
+
|
|
16
|
+
The public SDNQ checkpoint was selected instead of the AI Farm LoRA/heretic-text-encoder
|
|
17
|
+
variant so that quantizer choice is the main experimental difference. SDNQ uses UINT4
|
|
18
|
+
weights with BF16 activations. OrbitQuant uses 4-bit codebook weights and 4-bit codebook
|
|
19
|
+
activations.
|
|
20
|
+
|
|
21
|
+
OrbitQuant quantized 144 transformer projections and 252 text-encoder projections. Three
|
|
22
|
+
transformer modulation projections use INT4 RTN with BF16 activations, and the text
|
|
23
|
+
encoder `lm_head` remains BF16. Quantizing the text encoder is a deliberate universal
|
|
24
|
+
adapter extension for this comparison; the OrbitQuant paper leaves text encoders in BF16.
|
|
25
|
+
|
|
26
|
+
## Protocol
|
|
27
|
+
|
|
28
|
+
- GPU: NVIDIA L40S 48 GB (`sm_89`)
|
|
29
|
+
- Torch: 2.9.1+cu128
|
|
30
|
+
- CUDA: 12.8
|
|
31
|
+
- Diffusers: 0.39.0
|
|
32
|
+
- Transformers: 5.13.0
|
|
33
|
+
- OrbitQuant: 0.3.0
|
|
34
|
+
- SDNQ: 0.1.8
|
|
35
|
+
- Arithmetic: BF16
|
|
36
|
+
- CPU offload: disabled
|
|
37
|
+
- Output: 1024x1024
|
|
38
|
+
- Steps: 4
|
|
39
|
+
- Guidance: 1.0
|
|
40
|
+
- Seed: 0
|
|
41
|
+
- Batch size: 1
|
|
42
|
+
- Ten identical prompts per variant
|
|
43
|
+
- Each variant loaded and ran in a separate process
|
|
44
|
+
- `PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True`
|
|
45
|
+
|
|
46
|
+
The prompt pack stresses micro-detail, exact counting, nested spatial composition,
|
|
47
|
+
fictional authorial style, abstract material separation, English fine print, Russian,
|
|
48
|
+
Japanese and Chinese typography, reflections, occlusion and a dense panoramic scene.
|
|
49
|
+
|
|
50
|
+
## Artifact Size
|
|
51
|
+
|
|
52
|
+
The table counts model weight payloads only, excluding cards and comparison images.
|
|
53
|
+
|
|
54
|
+
| Variant | Transformer | Text encoder | VAE | Total weights |
|
|
55
|
+
| --- | ---: | ---: | ---: | ---: |
|
|
56
|
+
| BF16 | 18.157 GB | 16.382 GB | 0.168 GB | 34.707 GB |
|
|
57
|
+
| SDNQ UINT4 | 5.616 GB | 6.397 GB | 0.168 GB | 12.181 GB |
|
|
58
|
+
| OrbitQuant W4A4 | 4.705 GB | 5.966 GB | 0.168 GB | 10.839 GB |
|
|
59
|
+
|
|
60
|
+
OrbitQuant's weight payload is 68.8% smaller than BF16 and 11.0% smaller than the
|
|
61
|
+
controlled SDNQ artifact. The complete loadable OrbitQuant pipeline before its model-card
|
|
62
|
+
matrix is 10.85 GB.
|
|
63
|
+
|
|
64
|
+
## Runtime
|
|
65
|
+
|
|
66
|
+
The OrbitQuant row used a locally built ABI3 CUDA package from
|
|
67
|
+
`native-kernels/orbitquant-packed-matmul`; Kernel Hub was not involved. All 396
|
|
68
|
+
packed projections selected `native_packed_matmul` and the optimized W4A4 path.
|
|
69
|
+
|
|
70
|
+
| Variant | Load | Cold image | Hot mean | Hot median | Hot p95 |
|
|
71
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
72
|
+
| SDNQ UINT4 | 5.918 s | 16.956 s | 2.0885 s | 2.0875 s | 2.0966 s |
|
|
73
|
+
| OrbitQuant W4A4 | 2.543 s | 4.193 s | 2.0907 s | 2.0920 s | 2.0988 s |
|
|
74
|
+
|
|
75
|
+
| Variant | Load NVML peak | Hot NVML peak | CUDA allocated peak | CUDA reserved peak |
|
|
76
|
+
| --- | ---: | ---: | ---: | ---: |
|
|
77
|
+
| SDNQ UINT4 | 13.383 GB | 17.564 GB | 14.844 GB | 16.377 GB |
|
|
78
|
+
| OrbitQuant W4A4 | 11.959 GB | 15.731 GB | 13.942 GB | 14.544 GB |
|
|
79
|
+
|
|
80
|
+
OrbitQuant's hot mean was 0.11% slower than SDNQ, which is practical parity for
|
|
81
|
+
this run. OrbitQuant loaded 57.0% faster, used 0.902 GB less peak CUDA allocated
|
|
82
|
+
memory, and used 1.833 GB less peak CUDA reserved and NVML memory. The packed
|
|
83
|
+
weight payload also remains 11.0% smaller.
|
|
84
|
+
|
|
85
|
+
The selected CUDA path performs native token norm, RPBH/FWHT and codebook-bin
|
|
86
|
+
selection, emits an INT8 surrogate of the 4-bit activation codebook, decodes
|
|
87
|
+
only a bounded output-channel chunk of the packed W4 weights, calls the
|
|
88
|
+
CUTLASS-backed `torch._int_mm`, and applies norms, scales and bias in a Triton
|
|
89
|
+
epilogue. It does not materialize a full BF16/FP16 weight matrix. The direct
|
|
90
|
+
packed CUDA MMA implementation remains the fallback for unsupported shapes.
|
|
91
|
+
|
|
92
|
+
The optimized path adds a small runtime approximation beyond the paper
|
|
93
|
+
equation: fixed Lloyd-Max centroids are represented by symmetric INT8 codes and
|
|
94
|
+
one scalar per codebook. Packed indices and the checkpoint are unchanged;
|
|
95
|
+
`runtime_mode="dequant_bf16"` remains the exact-centroid reference. Local build
|
|
96
|
+
and verification instructions are in [the kernel audit](kernel-audit.md#local-native-package).
|
|
97
|
+
|
|
98
|
+
## Paired Visual Comparison
|
|
99
|
+
|
|
100
|
+
The matrix is a separate controlled A40 visual run using full 1024x1024 tiles
|
|
101
|
+
and WebP quality 95. Every column uses the same prompt, seed and pipeline
|
|
102
|
+
settings. The L40S production-default OrbitQuant rerun produced ten finite
|
|
103
|
+
images that matched the previously validated optimized W4A4 outputs byte for
|
|
104
|
+
byte.
|
|
105
|
+
|
|
106
|
+

|
|
107
|
+
|
|
108
|
+
## Visual Assessment
|
|
109
|
+
|
|
110
|
+
- **No collapse:** all thirty outputs are finite, coherent and detailed. OrbitQuant did not
|
|
111
|
+
produce blank, noisy or structurally broken images.
|
|
112
|
+
- **Micro-detail and materials:** all three variants preserve gears, filigree, architectural
|
|
113
|
+
interiors, paper grain, metal, resin and reflected surfaces. OrbitQuant remains competitive
|
|
114
|
+
with BF16 and SDNQ in these cases.
|
|
115
|
+
- **Dense composition:** all variants retain foreground/background separation and the main
|
|
116
|
+
hierarchy in the architectural cutaway and orbital-banquet prompts. Individual requested
|
|
117
|
+
objects move or disappear because quantization changes the denoising trajectory.
|
|
118
|
+
- **Counting:** none of the variants reliably renders exactly nine performers or every exact
|
|
119
|
+
repeated motif. This is a base-model limitation in the tested setting rather than an
|
|
120
|
+
OrbitQuant-only collapse.
|
|
121
|
+
- **English typography:** SDNQ is strongest on the small four-line specification table.
|
|
122
|
+
OrbitQuant preserves the headline and subtitle but misspells or truncates some fine print.
|
|
123
|
+
- **Russian typography:** all variants render the large headline, subtitle and archive stamp
|
|
124
|
+
well; small contents text contains errors in every column.
|
|
125
|
+
- **Japanese and Chinese typography:** visual glyph quality is plausible, but exact requested
|
|
126
|
+
strings are not reliably reproduced by any variant.
|
|
127
|
+
- **Trajectory fidelity:** SDNQ often stays visually closer to BF16. OrbitQuant also quantizes
|
|
128
|
+
activations and therefore produces larger compositional changes at the same seed.
|
|
129
|
+
|
|
130
|
+
This assessment is subjective and paired. It demonstrates non-collapse and exposes concrete
|
|
131
|
+
failure modes; it is not a substitute for GenEval or another task-specific objective metric.
|
|
132
|
+
|
|
133
|
+
## Result
|
|
134
|
+
|
|
135
|
+
OrbitQuant produces the smaller complete 4-bit pipeline, additionally quantizes
|
|
136
|
+
activations without calibration data, and reaches SDNQ hot-generation parity on
|
|
137
|
+
the tested L40S while using materially less runtime memory. The visual matrix
|
|
138
|
+
shows preserved complex structure without collapse; SDNQ remains closer to BF16
|
|
139
|
+
on some typography cases. This is a controlled result for FLUX.2 Klein 9B, not a
|
|
140
|
+
universal speed claim for every model or GPU.
|
|
141
|
+
|
|
142
|
+
Machine-readable metrics and the exact ten prompts are included with the
|
|
143
|
+
[OrbitQuant checkpoint](https://huggingface.co/WaveCut/FLUX.2-klein-9B-OrbitQuant-W4A4).
|
|
@@ -10,7 +10,7 @@ when explicitly selected.
|
|
|
10
10
|
|
|
11
11
|
| Device | Default dispatch | Required support |
|
|
12
12
|
| --- | --- | --- |
|
|
13
|
-
| CUDA | Native packed
|
|
13
|
+
| CUDA | Native activation kernel plus packed W4A4 tensor-core path; native or Triton packed fallback | An importable local native package and, for the CUTLASS path, Triton |
|
|
14
14
|
| MPS | Native packed matmul | An importable local Metal package |
|
|
15
15
|
| CPU | Reference matmul | PyTorch |
|
|
16
16
|
|
|
@@ -26,7 +26,7 @@ Other explicit modes are `native_packed_matmul`, `triton_packed_matmul`,
|
|
|
26
26
|
|
|
27
27
|
| Backend | Status | Implemented path |
|
|
28
28
|
| --- | --- | --- |
|
|
29
|
-
| CUDA | Optimized packed inference | Native
|
|
29
|
+
| CUDA | Optimized packed inference | Native RPBH/quantization, chunked packed-weight decode plus CUTLASS INT8 matmul, direct packed CUDA MMA fallback, and generic Triton packed fallback |
|
|
30
30
|
| MPS/Metal | Optimized packed inference | Native Metal packed matmul and Metal activation quantization stages |
|
|
31
31
|
| CPU | Reference | PyTorch activation quantization, weight dequantization, and linear matmul |
|
|
32
32
|
| ROCm | Unsupported | No release backend |
|
|
@@ -60,6 +60,27 @@ TORCH_CUDA_ARCH_LIST="8.9" CUDACXX=/usr/local/cuda/bin/nvcc \
|
|
|
60
60
|
export PYTHONPATH="$PWD/build/<matching-cuda-variant>:$PYTHONPATH"
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
+
For a locally built Metal variant that remains loadable on macOS 15 and newer:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cargo install --git https://github.com/huggingface/kernels hf-kernel-builder
|
|
67
|
+
cd native-kernels/orbitquant-packed-matmul
|
|
68
|
+
kernel-builder check-config .
|
|
69
|
+
kernel-builder create-pyproject -f .
|
|
70
|
+
MACOSX_DEPLOYMENT_TARGET=15.0 \
|
|
71
|
+
CMAKE_ARGS="-DCMAKE_OSX_DEPLOYMENT_TARGET=15.0" \
|
|
72
|
+
python setup.py build_kernel
|
|
73
|
+
kernel-builder check-abi --macos 15.0 --python-abi 3.9 .
|
|
74
|
+
export PYTHONPATH="$PWD/build/<matching-metal-variant>:$PYTHONPATH"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
For PyTorch 2.9 CUDA workloads, enable expandable allocator segments before the
|
|
78
|
+
Python process starts to minimize reserved/NVML memory:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True python generate.py
|
|
82
|
+
```
|
|
83
|
+
|
|
63
84
|
The generated `setup.py` and CMake files come from `kernel-builder` and must not
|
|
64
85
|
be committed. This development build targets the current host toolchain. Use the
|
|
65
86
|
Nix build for a redistributable variant and run `kernel-builder check-abi` before
|
|
@@ -96,37 +117,67 @@ dequantization or `F.linear` fallback in optimized mode.
|
|
|
96
117
|
MPS verification passed on Apple Silicon with Torch 2.12.1. It covered the
|
|
97
118
|
native Metal package, inline shader stages, `auto_fused` dispatch, and a real
|
|
98
119
|
3072x3072 projection restored from the published FLUX.2 W4A4 artifact. The
|
|
99
|
-
|
|
120
|
+
macOS 15 deployment-target build passed `kernel-builder check-abi` for the
|
|
121
|
+
Python 3.9 stable ABI, and the packed and reference outputs were finite and
|
|
122
|
+
numerically close.
|
|
100
123
|
|
|
101
124
|
The Metal package also passed an ABI3 build matrix for Torch 2.11, 2.12, and
|
|
102
125
|
2.13. A quantized tiny GPT-2 run exercised all eight wrapped projections during
|
|
103
126
|
prefill and cached decode through `native_packed_matmul`, with finite outputs.
|
|
104
127
|
|
|
105
|
-
The
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
no-bias paths, partial output tiles,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
The
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
The final CUDA W4A4 stack was built and tested on an NVIDIA L40S (`sm_89`) with
|
|
129
|
+
Torch 2.9.1+cu128 and CUDA 12.8. The native package suite passed 49 CUDA tests;
|
|
130
|
+
the ten skipped cases were Metal-only. Coverage includes W2/W3/W4/W6 generic
|
|
131
|
+
packed matmul, FP16/BF16, bias and no-bias paths, partial output tiles, direct
|
|
132
|
+
packed W4A4 MMA, native packed-A4 activation quantization, and native INT8
|
|
133
|
+
activation quantization for full-block dimensions and the 12288/4096 blocked
|
|
134
|
+
RPBH case.
|
|
135
|
+
|
|
136
|
+
For W4A4 on compute capability 8.0 or newer, the selected path is:
|
|
137
|
+
|
|
138
|
+
1. A native CUDA launch computes token norms, applies RPBH/FWHT, selects the
|
|
139
|
+
fixed Lloyd-Max bins, and emits INT8 surrogate codes.
|
|
140
|
+
2. Packed row-major W4 indices are decoded one bounded output-channel chunk at
|
|
141
|
+
a time; the complete floating-point weight matrix is never materialized.
|
|
142
|
+
3. `torch._int_mm` dispatches the INT8 matrix product to CUTLASS tensor cores.
|
|
143
|
+
4. A Triton epilogue applies token norms, BF16 row norms, both surrogate scales,
|
|
144
|
+
and bias.
|
|
145
|
+
|
|
146
|
+
The direct packed CUDA MMA implementation remains available for unsupported
|
|
147
|
+
CUTLASS shapes. It includes asynchronous packed loads and SM89-specific tile
|
|
148
|
+
selection. The checkpoint keeps the original row-major four-bit payload; no
|
|
149
|
+
repacked duplicate weights are stored.
|
|
150
|
+
|
|
151
|
+
The selected production dispatch was also profiled on an NVIDIA GeForce RTX
|
|
152
|
+
4090 (`sm_89`) with Torch 2.9.1+cu128 and CUDA 12.8. For a representative
|
|
153
|
+
FLUX.2 fused-input projection with 4608 activation rows, 4096 input channels,
|
|
154
|
+
and 36864 output channels, ten post-warmup calls measured 4.317 ms median,
|
|
155
|
+
4.352 ms mean, and 0.867 GB peak allocated memory. The output was finite and
|
|
156
|
+
the dispatch reported `native_packed_matmul` with
|
|
157
|
+
`native_cuda_int8_surrogate` activation quantization.
|
|
158
|
+
|
|
159
|
+
Nsight Systems attributed 77.8% of GPU kernel time to the CUTLASS INT8 GEMM,
|
|
160
|
+
10.0% to the fused scale/norm/bias epilogue, 8.2% to bounded packed-W4 decode,
|
|
161
|
+
and 4.0% to native token norm, RPBH/FWHT, and codebook assignment. The same
|
|
162
|
+
shape measured 4.809 ms median on the L40S. Nsight Compute performance counters
|
|
163
|
+
were unavailable on the hosted 4090 because the provider disabled GPU counter
|
|
164
|
+
access (`ERR_NVGPUCTRPERM`); the Systems trace and CUDA event timings do not
|
|
165
|
+
depend on those counters.
|
|
166
|
+
|
|
167
|
+
A full FLUX.2 Klein 9B W4A4 pipeline exercised all 396 packed projections
|
|
168
|
+
across the transformer and Qwen3 text encoder. The controlled native run used
|
|
169
|
+
1024x1024 output, four steps, guidance 1.0, seed 0, and ten identical prompts:
|
|
170
|
+
|
|
171
|
+
| Runtime | Load | Hot mean | Hot median | CUDA allocated peak | CUDA reserved peak | NVML peak |
|
|
172
|
+
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
173
|
+
| SDNQ UINT4 | 5.918 s | 2.0885 s | 2.0875 s | 14.844 GB | 16.377 GB | 17.564 GB |
|
|
174
|
+
| OrbitQuant W4A4 | 2.543 s | 2.0907 s | 2.0920 s | 13.942 GB | 14.544 GB | 15.731 GB |
|
|
175
|
+
|
|
176
|
+
OrbitQuant was within 0.11% of SDNQ hot mean while using 0.902 GB less CUDA
|
|
177
|
+
allocated memory and 1.833 GB less reserved/NVML memory. Every projection
|
|
178
|
+
reported `native_cuda_int8_surrogate`; no full-weight dequantization path was
|
|
179
|
+
entered. The ten deterministic outputs were finite and matched the separately
|
|
180
|
+
validated cumulative W4A4 run byte for byte.
|
|
130
181
|
|
|
131
182
|
Measured W4 BF16 operator latency for `in_features=768` and
|
|
132
183
|
`out_features=2304`:
|
|
@@ -202,9 +253,12 @@ python scripts/verify_hf_kernel_model_artifact.py \
|
|
|
202
253
|
## Performance Claims
|
|
203
254
|
|
|
204
255
|
Packed execution reduces weight-side materialization and runtime memory for the
|
|
205
|
-
validated image pipelines.
|
|
206
|
-
|
|
207
|
-
|
|
256
|
+
validated image pipelines. On the controlled L40S FLUX.2 Klein 9B comparison,
|
|
257
|
+
the optimized W4A4 path reached practical SDNQ hot-generation parity with lower
|
|
258
|
+
allocated, reserved, and NVML memory. Throughput still depends on model shapes,
|
|
259
|
+
device, Torch, offload policy, and backend. Wan with CPU offload did not show a
|
|
260
|
+
throughput or peak-memory improvement in the recorded native run. OrbitQuant
|
|
261
|
+
does not claim a universal speedup.
|
|
208
262
|
|
|
209
263
|
Synthetic operator benchmarks are diagnostics. Results above compare packed
|
|
210
264
|
execution with both weight materialization plus `F.linear` and, where stated,
|
|
@@ -65,7 +65,7 @@ Status legend:
|
|
|
65
65
|
| Embeddings, timestep MLPs, final projection/unpatchify heads, text encoders, VAE, scheduler, safety/image processors remain unquantized by default. | Pass for configured transformer components | `src/orbitquant/policies/generic_dit.py`, `tests/test_target_policies.py`; inventory summary below | Text encoders and VAE are outside the transformer component and are not passed into the default quantization helper. Artifact manifests still need per-artifact cross-checks before final publication. |
|
|
66
66
|
| Native settings match paper for FLUX.1-schnell, Z-Image-Turbo, and Wan 2.1-1.3B. | Pass for encoded settings | `src/orbitquant/eval/native_settings.py`, `README.md`, `src/orbitquant/artifacts/model_card.py` | Native artifact-readiness evidence is separate from release-grade metric tables. Full metric runs are required before metric-table or paper-reproduction claims. |
|
|
67
67
|
| FLUX.2 Klein is separated from paper-reproduction targets. | Pass | `src/orbitquant/eval/native_settings.py`, `src/orbitquant/artifacts/model_card.py` | It is treated as an additional target using paper-style native settings. |
|
|
68
|
-
| Runtime acceleration claims match implemented kernels. |
|
|
68
|
+
| Runtime acceleration claims match implemented kernels. | Pass for the measured FLUX.2 Klein 9B W4A4 configuration; partial across other models | `src/orbitquant/kernels/dispatch.py`, `src/orbitquant/kernels/triton_cuda.py`, `src/orbitquant/kernels/mps.py`, `tests/test_kernels.py`, `tests/test_orbit_linear.py`, `docs/kernel-audit.md` | Default `auto_fused` requires packed low-bit matmul on CUDA/MPS and fails loudly when kernels are missing. CUDA and MPS avoid full floating-point weight materialization. The CUDA INT8-surrogate fast path is an explicitly documented runtime approximation; exact Lloyd-Max centroid evaluation remains available through `dequant_bf16`. |
|
|
69
69
|
| Release-grade GenEval/VBench metrics are available for paper target claims. | Blocked for metric claims | `src/orbitquant/hub.py`, `src/orbitquant/eval/` | Missing metrics block only paper metric/reproduction claims. |
|
|
70
70
|
|
|
71
71
|
## Model Policy Evidence
|
|
@@ -126,7 +126,7 @@ metrics; they do not by themselves claim GenEval or VBench scores.
|
|
|
126
126
|
| Backend | Status | Evidence | Claim boundary |
|
|
127
127
|
| --- | --- | --- | --- |
|
|
128
128
|
| CPU | Pass as reference | `src/orbitquant/kernels/dispatch.py`, `src/orbitquant/functional.py` | Correctness baseline only; no optimized CPU kernel claim. |
|
|
129
|
-
| CUDA/Triton | Pass for packed fallback | `src/orbitquant/kernels/triton_cuda.py`, `tests/test_kernels.py`, `tests/test_orbit_linear.py`, `docs/kernel-audit.md` |
|
|
129
|
+
| CUDA/native/Triton | Pass for optimized W4A4 and packed fallback | `native-kernels/orbitquant-packed-matmul`, `src/orbitquant/kernels/native_packed_matmul.py`, `src/orbitquant/kernels/triton_cuda.py`, `tests/test_native_packed_matmul.py`, `tests/test_kernels.py`, `tests/test_orbit_linear.py`, `docs/kernel-audit.md` | The selected W4A4 path fuses norm/RPBH/FWHT/codebook assignment to INT8 surrogate activations, decodes bounded W4 chunks, uses CUTLASS INT8 matmul, and applies a fused epilogue. Direct packed CUDA MMA and generic Triton packed matmul remain fallbacks. No path selected by `auto_fused` materializes a full BF16/FP16 weight matrix. |
|
|
130
130
|
| MPS/Metal | Pass for native packed inference | `src/orbitquant/kernels/mps.py`, `src/orbitquant/kernels/dispatch.py`, `tests/test_kernels.py`, `tests/test_orbit_linear.py`, `docs/kernel-audit.md` | A fused Metal shader performs activation norm, RPBH/FWHT, codebook lookup, and rescale. The native package performs packed matmul for generic leading dimensions, including short decode rows and partial matrix tiles, without full weight materialization. Offline weight and AdaLN quantization remain reference paths on MPS. |
|
|
131
131
|
| ROCm | Blocked for backend claim | No implementation in current tree | Do not claim ROCm optimization. |
|
|
132
132
|
| XPU | Blocked for backend claim | No implementation in current tree | Do not claim XPU optimization. |
|
|
@@ -136,6 +136,11 @@ metrics; they do not by themselves claim GenEval or VBench scores.
|
|
|
136
136
|
- `runtime_mode="auto_fused"` is the default optimized policy. It avoids silent
|
|
137
137
|
CUDA/MPS fallback to full dequantized BF16 weight materialization. Explicit
|
|
138
138
|
`runtime_mode="dequant_bf16"` remains the compatibility/debug reference path.
|
|
139
|
+
- The CUDA W4A4 tensor-core path retains the paper's packed nearest-centroid
|
|
140
|
+
indices but approximates each fixed Lloyd-Max centroid with a symmetric INT8
|
|
141
|
+
code and one scalar per codebook. Measured codebook relative RMSE is
|
|
142
|
+
0.21-0.28% for the FLUX.2 dimensions. This extra approximation is not part of
|
|
143
|
+
the paper equation and is never presented as the exact reference path.
|
|
139
144
|
|
|
140
145
|
## Native Eval And Claim Policy
|
|
141
146
|
|
|
@@ -172,7 +177,8 @@ not silently substitute a different quantization method.
|
|
|
172
177
|
| --- | --- | --- |
|
|
173
178
|
| Explicit `dequant_bf16` runtime uses dequantized BF16 matmul. | Accepted reference path | It is kept for compatibility and debugging. Do not claim it as low-bit fused inference. |
|
|
174
179
|
| Zero weight rows use an epsilon guard for direction quantization. | Accepted implementation guard | The paper defines weight directions as `w' / ||w'||` for nonzero rows. The implementation divides by `max(||w'||, ε)` only when choosing codebook indices, stores the raw BF16 row norm, and dequantizes zero rows back to exactly zero. |
|
|
175
|
-
|
|
|
180
|
+
| The optimized CUDA W4A4 path evaluates an INT8 surrogate of each Lloyd-Max codebook. | Documented runtime deviation | Packed nearest-centroid indices, row norms, token norms, and the artifact remain unchanged. The surrogate adds 0.21-0.28% codebook relative RMSE for the measured FLUX.2 dimensions. `dequant_bf16` evaluates the stored Lloyd-Max centroids directly and is the exact methodology reference. |
|
|
181
|
+
| Full-model speedup is configuration-specific. | Accepted claim boundary | FLUX.2 Klein 9B on L40S reached practical SDNQ hot-generation parity with lower memory. That result does not establish universal speedup for other models, shapes, GPUs, or offload policies. |
|
|
176
182
|
| The paper's block-size enumeration omits `h=256`, although its stated largest-power-of-two-divisor rule gives `h=256` for Z-Image `d=3840` and Wan `d=8960` projections. | Paper inconsistency | The implementation follows the formal rule. The selected target dimensions produce `h` in `{256, 512, 1024, 2048, 4096}`. |
|
|
177
183
|
| Published checkpoints use converged Lloyd-Max codebook version 2 and `activation_eps=1e-10`. | Pass | All 14 canonical FLUX.2, FLUX.1-schnell, Z-Image-Turbo, and Wan2.1 artifacts were regenerated and validated. Legacy version 1 artifacts remain loadable by the library but are no longer the published release checkpoints. |
|
|
178
184
|
| Full config-derived inventories are audit artifacts, not committed source files. | Accepted artifact hygiene choice | Inventory summaries are recorded above; raw JSON may remain unpublished to avoid turning the repository into an artifact store. |
|
|
@@ -36,6 +36,21 @@ Inputs:
|
|
|
36
36
|
`x` may be `float32`, `float16`, or `bfloat16`. The output has shape
|
|
37
37
|
`[..., out_features]` and the same dtype as `x`.
|
|
38
38
|
|
|
39
|
+
The CUDA package also exports the operations used by OrbitQuant's W4A4 runtime:
|
|
40
|
+
|
|
41
|
+
- `quantize_activations_int8`: token norm, RPBH/FWHT, nearest-codebook
|
|
42
|
+
assignment, and INT8-surrogate output in one native launch.
|
|
43
|
+
- `quantize_activations_packed_w4`: the same activation path with packed 4-bit
|
|
44
|
+
output for the direct packed matmul fallback.
|
|
45
|
+
- `matmul_packed_w4a4_int8`: direct packed A4/W4 CUDA MMA with fused token norm,
|
|
46
|
+
row norm, surrogate scales, and bias epilogue.
|
|
47
|
+
|
|
48
|
+
On CUDA compute capability 8.0 or newer, OrbitQuant normally combines
|
|
49
|
+
`quantize_activations_int8` with chunked packed-weight decode and Torch's
|
|
50
|
+
CUTLASS-backed INT8 matmul. The direct packed MMA operation remains available
|
|
51
|
+
when that path is unsupported. Neither path materializes a complete BF16/FP16
|
|
52
|
+
weight matrix.
|
|
53
|
+
|
|
39
54
|
## Build And Test
|
|
40
55
|
|
|
41
56
|
```bash
|
|
@@ -61,6 +76,18 @@ TORCH_CUDA_ARCH_LIST="8.9" CUDACXX=/usr/local/cuda/bin/nvcc \
|
|
|
61
76
|
python setup.py build_kernel
|
|
62
77
|
```
|
|
63
78
|
|
|
79
|
+
For a local Metal build compatible with macOS 15 and newer:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
cargo install --git https://github.com/huggingface/kernels hf-kernel-builder
|
|
83
|
+
kernel-builder check-config .
|
|
84
|
+
kernel-builder create-pyproject -f .
|
|
85
|
+
MACOSX_DEPLOYMENT_TARGET=15.0 \
|
|
86
|
+
CMAKE_ARGS="-DCMAKE_OSX_DEPLOYMENT_TARGET=15.0" \
|
|
87
|
+
python setup.py build_kernel
|
|
88
|
+
kernel-builder check-abi --macos 15.0 --python-abi 3.9 .
|
|
89
|
+
```
|
|
90
|
+
|
|
64
91
|
This generated project is for local testing and must not be committed or
|
|
65
92
|
distributed without a successful `kernel-builder check-abi`. Use the Nix build
|
|
66
93
|
for redistributable variants.
|
|
@@ -74,6 +101,13 @@ export PYTHONPATH="/path/to/build/torch212-metal-aarch64-darwin:$PYTHONPATH"
|
|
|
74
101
|
python -c "import orbitquant_packed_matmul; print(orbitquant_packed_matmul)"
|
|
75
102
|
```
|
|
76
103
|
|
|
104
|
+
For PyTorch 2.9 CUDA inference, set the allocator before starting Python when
|
|
105
|
+
minimum reserved memory is important:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True python generate.py
|
|
109
|
+
```
|
|
110
|
+
|
|
77
111
|
OrbitQuant detects that importable package before trying any Hub loader. For
|
|
78
112
|
Hugging Face `kernels` local loading instead, set `LOCAL_KERNELS` to the same
|
|
79
113
|
built variant directory containing `metadata.json`, not to the source package
|
|
@@ -118,3 +152,6 @@ It also reports storage accounting for the packed weight path:
|
|
|
118
152
|
`packed_weight_path_vs_materialized_weight_ratio`. These values describe only
|
|
119
153
|
the weight-side storage used by this operator; they are not end-to-end model
|
|
120
154
|
VRAM measurements.
|
|
155
|
+
|
|
156
|
+
End-to-end FLUX.2 Klein 9B measurements and the SDNQ comparison are recorded in
|
|
157
|
+
[`docs/flux2-klein-9b-sdnq-vs-orbitquant.md`](../../docs/flux2-klein-9b-sdnq-vs-orbitquant.md).
|