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.
Files changed (134) hide show
  1. {orbitquant-0.2.2 → orbitquant-0.3.0}/PKG-INFO +21 -2
  2. {orbitquant-0.2.2 → orbitquant-0.3.0}/README.md +20 -1
  3. orbitquant-0.3.0/docs/assets/flux2-klein-9b-sdnq-vs-orbitquant.webp +0 -0
  4. orbitquant-0.3.0/docs/flux2-klein-9b-sdnq-vs-orbitquant.md +143 -0
  5. {orbitquant-0.2.2 → orbitquant-0.3.0}/docs/kernel-audit.md +85 -31
  6. {orbitquant-0.2.2 → orbitquant-0.3.0}/docs/paper-methodology-audit.md +9 -3
  7. {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/CARD.md +37 -0
  8. orbitquant-0.3.0/native-kernels/orbitquant-packed-matmul/orbitquant_packed_matmul_cuda/packed_matmul.cu +1742 -0
  9. {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/tests/test_packed_matmul.py +256 -34
  10. orbitquant-0.3.0/native-kernels/orbitquant-packed-matmul/torch-ext/orbitquant_packed_matmul/__init__.py +251 -0
  11. orbitquant-0.3.0/native-kernels/orbitquant-packed-matmul/torch-ext/torch_binding.cpp +42 -0
  12. orbitquant-0.3.0/native-kernels/orbitquant-packed-matmul/torch-ext/torch_binding.h +62 -0
  13. {orbitquant-0.2.2 → orbitquant-0.3.0}/pyproject.toml +1 -1
  14. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/__init__.py +1 -1
  15. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/kernels/native_packed_matmul.py +125 -2
  16. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/kernels/triton_cuda.py +535 -0
  17. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/layers.py +244 -10
  18. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_ci.py +3 -1
  19. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_documentation.py +8 -1
  20. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_native_packed_matmul.py +39 -0
  21. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_orbit_linear.py +104 -18
  22. {orbitquant-0.2.2 → orbitquant-0.3.0}/uv.lock +1 -1
  23. orbitquant-0.2.2/native-kernels/orbitquant-packed-matmul/orbitquant_packed_matmul_cuda/packed_matmul.cu +0 -847
  24. orbitquant-0.2.2/native-kernels/orbitquant-packed-matmul/torch-ext/orbitquant_packed_matmul/__init__.py +0 -61
  25. orbitquant-0.2.2/native-kernels/orbitquant-packed-matmul/torch-ext/torch_binding.cpp +0 -18
  26. orbitquant-0.2.2/native-kernels/orbitquant-packed-matmul/torch-ext/torch_binding.h +0 -18
  27. {orbitquant-0.2.2 → orbitquant-0.3.0}/.github/workflows/ci.yml +0 -0
  28. {orbitquant-0.2.2 → orbitquant-0.3.0}/.github/workflows/publish-pypi.yml +0 -0
  29. {orbitquant-0.2.2 → orbitquant-0.3.0}/.gitignore +0 -0
  30. {orbitquant-0.2.2 → orbitquant-0.3.0}/LICENSE +0 -0
  31. {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/benchmarks/benchmark.py +0 -0
  32. {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/build.toml +0 -0
  33. {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/example.py +0 -0
  34. {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/flake.lock +0 -0
  35. {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/flake.nix +0 -0
  36. {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/orbitquant_packed_matmul_metal/packed_matmul.metal +0 -0
  37. {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/orbitquant_packed_matmul_metal/packed_matmul.mm +0 -0
  38. {orbitquant-0.2.2 → orbitquant-0.3.0}/native-kernels/orbitquant-packed-matmul/tests/__init__.py +0 -0
  39. {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/run_cuda_kernel_checks.sh +0 -0
  40. {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/run_hf_compat_checks.sh +0 -0
  41. {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/run_mps_kernel_checks.sh +0 -0
  42. {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/run_paper_methodology_checks.sh +0 -0
  43. {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/runpod_ssh_health.sh +0 -0
  44. {orbitquant-0.2.2 → orbitquant-0.3.0}/scripts/verify_hf_kernel_model_artifact.py +0 -0
  45. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/adaln.py +0 -0
  46. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/__init__.py +0 -0
  47. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/assets.py +0 -0
  48. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/benchmark.py +0 -0
  49. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/checksums.py +0 -0
  50. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/comparisons.py +0 -0
  51. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/loader.py +0 -0
  52. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/manifest.py +0 -0
  53. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/model_card.py +0 -0
  54. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/refresh.py +0 -0
  55. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/repair.py +0 -0
  56. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/validator.py +0 -0
  57. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/artifacts/writer.py +0 -0
  58. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/benchmarks.py +0 -0
  59. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/cli/__init__.py +0 -0
  60. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/cli/main.py +0 -0
  61. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/codebooks/__init__.py +0 -0
  62. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/codebooks/lloyd_max.py +0 -0
  63. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/config.py +0 -0
  64. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/errors.py +0 -0
  65. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/__init__.py +0 -0
  66. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/assets.py +0 -0
  67. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/external_export.py +0 -0
  68. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/external_metrics.py +0 -0
  69. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/external_plan.py +0 -0
  70. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/metrics.py +0 -0
  71. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/native_plan.py +0 -0
  72. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/native_runner.py +0 -0
  73. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/native_settings.py +0 -0
  74. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/prompts.py +0 -0
  75. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/eval/report.py +0 -0
  76. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/functional.py +0 -0
  77. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/hub.py +0 -0
  78. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/kernels/__init__.py +0 -0
  79. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/kernels/dispatch.py +0 -0
  80. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/kernels/mps.py +0 -0
  81. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/linear_adapters.py +0 -0
  82. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/modeling.py +0 -0
  83. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/packing/__init__.py +0 -0
  84. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/packing/bitpack.py +0 -0
  85. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/pipeline.py +0 -0
  86. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/__init__.py +0 -0
  87. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/flux.py +0 -0
  88. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/flux2.py +0 -0
  89. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/generic_dit.py +0 -0
  90. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/wan.py +0 -0
  91. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/policies/z_image.py +0 -0
  92. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/quantizer.py +0 -0
  93. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/recipes.py +0 -0
  94. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/rotations/__init__.py +0 -0
  95. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/rotations/fwht.py +0 -0
  96. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/rotations/rpbh.py +0 -0
  97. {orbitquant-0.2.2 → orbitquant-0.3.0}/src/orbitquant/transformers_ops.py +0 -0
  98. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_adaln_rtn.py +0 -0
  99. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_artifact_writer.py +0 -0
  100. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_benchmarks.py +0 -0
  101. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_bitpack.py +0 -0
  102. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_cli.py +0 -0
  103. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_cli_report.py +0 -0
  104. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_codebooks.py +0 -0
  105. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_config.py +0 -0
  106. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_diffusers_modelmixin_integration.py +0 -0
  107. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_distribution.py +0 -0
  108. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_eval_assets.py +0 -0
  109. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_eval_prompts.py +0 -0
  110. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_eval_report.py +0 -0
  111. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_external_eval_plan.py +0 -0
  112. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_external_export.py +0 -0
  113. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_hub.py +0 -0
  114. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_kernel_model_verifier.py +0 -0
  115. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_kernels.py +0 -0
  116. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_linear_adapters.py +0 -0
  117. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_manifest.py +0 -0
  118. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_model_card.py +0 -0
  119. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_model_quantization.py +0 -0
  120. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_native_kernel_package.py +0 -0
  121. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_native_runner.py +0 -0
  122. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_native_settings.py +0 -0
  123. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_optional_dependencies.py +0 -0
  124. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_paper_alignment.py +0 -0
  125. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_paper_methodology.py +0 -0
  126. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_pipeline_helpers.py +0 -0
  127. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_policies.py +0 -0
  128. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_prompt_jobs.py +0 -0
  129. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_prompt_selection.py +0 -0
  130. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_quantizer_adapter.py +0 -0
  131. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_rpbh.py +0 -0
  132. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_target_policies.py +0 -0
  133. {orbitquant-0.2.2 → orbitquant-0.3.0}/tests/test_transformers_pretrained_integration.py +0 -0
  134. {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.2.2
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 CUDA package, then Triton packed matmul |
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 CUDA package, then Triton packed matmul |
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
@@ -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
+ ![BF16, SDNQ UINT4 and OrbitQuant W4A4 across ten difficult prompts](assets/flux2-klein-9b-sdnq-vs-orbitquant.webp)
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 matmul, then Triton packed matmul | An importable local native package or Triton |
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 CUDA packed matmul; Triton activation norm, RPBH/FWHT, codebook lookup, rescale, and packed matmul fallback |
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
- packed and reference outputs were finite and numerically close.
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 native CUDA package was also built and tested on an NVIDIA RTX 4090
106
- (`sm_89`) with Torch 2.9.1+cu128, CUDA 12.8, and kernel-builder 0.17.0-dev0.
107
- All 34 applicable package tests passed for W2/W3/W4/W6, FP16/BF16, bias and
108
- no-bias paths, partial output tiles, short rows, and tensor-core rows.
109
-
110
- The same local package build passed its 34 CUDA tests on an NVIDIA A40
111
- (`sm_86`) with Torch 2.9.1+cu128 and CUDA 12.8. A full FLUX.2 Klein 9B W4A4
112
- pipeline exercised 396 packed linears across the transformer and Qwen3 text
113
- encoder. Native 1024x1024 generation at four steps used
114
- `native_packed_matmul` for every packed linear and the Triton activation path;
115
- no full weight matrix was materialized.
116
-
117
- Representative A40 W4A4 layer timings from that pipeline are:
118
-
119
- | Projection | Rows | Shape | RPBH + activation quantization | Native packed matmul | Full layer |
120
- | --- | ---: | ---: | ---: | ---: | ---: |
121
- | Double-stream Q | 4096 | 4096 -> 4096 | 0.698 ms | 2.607 ms | 3.279 ms |
122
- | Single-stream fused input | 4608 | 4096 -> 36864 | 0.770 ms | 25.962 ms | 26.677 ms |
123
- | Single-stream output | 4608 | 16384 -> 4096 | 4.257 ms | 11.244 ms | 15.514 ms |
124
-
125
- The corresponding full-pipeline hot-generation mean was 7.418 seconds with a
126
- 17.66 GB NVML peak. On the same A40 and prompt pack, BF16 measured 3.911
127
- seconds and 40.83 GB, while SDNQ UINT4 measured 3.546 seconds and 17.55 GB.
128
- These results establish the memory reduction and the remaining throughput gap;
129
- they do not support a model-level speedup claim for OrbitQuant on A40.
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. Throughput depends on model shapes, device, Torch,
206
- offload policy, and backend. Wan with CPU offload did not show a throughput or
207
- peak-memory improvement in the recorded native run. OrbitQuant does not claim a universal speedup.
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. | Partial | `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` | Default `auto_fused` requires packed low-bit matmul on CUDA/MPS and fails loudly when kernels are missing. CUDA and MPS avoid full weight materialization; throughput varies by model and is reported only from measured benchmarks. |
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` | Covers activation norm/RPBH/lookup/rescale, low-bit pack/unpack, offline weight quantization, AdaLN RTN quant/dequant, and packed matmul. Default `auto_fused` selects native packed matmul first, then Triton packed matmul when available. |
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
- | Full-model speedup is not yet a release claim. | Accepted claim boundary | `auto_fused`, `native_packed_matmul`, and `triton_packed_matmul` use packed matmul paths, but model-specific benchmark artifacts are still required before broad acceleration claims. |
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).