hip-quant 2.2.0__tar.gz → 2.2.1__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.
- {hip_quant-2.2.0/hip_quant.egg-info → hip_quant-2.2.1}/PKG-INFO +151 -26
- {hip_quant-2.2.0 → hip_quant-2.2.1}/README.md +148 -25
- {hip_quant-2.2.0 → hip_quant-2.2.1}/_C.cp312-win_amd64.pyd +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/__init__.py +19 -2
- {hip_quant-2.2.0 → hip_quant-2.2.1}/build.ps1 +40 -29
- {hip_quant-2.2.0 → hip_quant-2.2.1}/device_info.py +6 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/gguf.py +14 -2
- {hip_quant-2.2.0 → hip_quant-2.2.1}/gguf_loader.py +10 -2
- {hip_quant-2.2.0 → hip_quant-2.2.1/hip_quant.egg-info}/PKG-INFO +151 -26
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hip_quant.egg-info/SOURCES.txt +4 -0
- hip_quant-2.2.1/hip_quant.egg-info/requires.txt +7 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hip_quantize.cpp +1 -1
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hip_quantize.dll +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hip_quantize_rocm721.dll +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/archive.py +2 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/format.py +4 -1
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/hq3.py +2 -1
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/hq8.py +2 -1
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/safetensors_numpy.py +4 -3
- {hip_quant-2.2.0 → hip_quant-2.2.1}/pyproject.toml +9 -1
- {hip_quant-2.2.0 → hip_quant-2.2.1}/setup.py +25 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/smi.py +32 -24
- hip_quant-2.2.1/tools/.gpu-smi-version +1 -0
- hip_quant-2.2.1/tools/fetch_gpu_smi.py +156 -0
- hip_quant-2.2.1/tools/gpu-smi.exe +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_api.py +27 -7
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/fp8_linear_kernels.hip +33 -33
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/gemv_q_kernels.hip +12 -6
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/mxfp4_to_fp8_kernels.hip +14 -11
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/pytorch_bindings.cpp +22 -4
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/wave_attn.hip +10 -1
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/wave_attn_long.hip +6 -1
- hip_quant-2.2.0/hip_quant.egg-info/requires.txt +0 -4
- hip_quant-2.2.0/tools/gpu-smi.exe +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/DOCUMENTATION.md +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/LICENSE +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/MANIFEST.in +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/__main__.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/bench_mxfp8.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/bench_wave_attn_inference.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/build.sh +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/cdna_compat.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/codebooks/iq1_s.bin +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/codebooks/iq2_xs.bin +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/codebooks/iq2_xxs.bin +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/codebooks/iq3_s.bin +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/codebooks/iq3_xxs.bin +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/demo.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/diagnose_fp8_crash.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/e2e_iq2s_iq1m.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/get_hf_tensors.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hip_iquant_util.h +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hip_quant.egg-info/dependency_links.txt +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hip_quant.egg-info/entry_points.txt +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hip_quant.egg-info/not-zip-safe +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hip_quant.egg-info/top_level.txt +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hip_quant_types.h +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hip_quant_util.h +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/__init__.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/__main__.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/analyzer.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/api.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/backends.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/mixed_policy.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/raw.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/sensitivity.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/torch_inference.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/hq2/transformers_loader.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/dequant_to_fp8.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/direct_fp8_quant.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/fp8_expand.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/fp8_gemm_test.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_aq2.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_bf16.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_f8_e4m3.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_f8_e5m2.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_hq2.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_iq1_m.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_iq1_s.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_iq2_s.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_iq2_xs.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_iq2_xxs.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_iq3_s.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_iq3_xxs.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_iq4_nl.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_iq4_xs.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q1_0.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q2_0.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q2_K.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q3_K.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q4_0.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q4_1.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q4_K.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q5_0.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q5_1.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q5_K.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q6_K.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q8_0.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q8_1.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_q8_K.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_tq1_0.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/quant_tq2_0.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/kernels/wmma_diag.cu +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/setup.cfg +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/setup_torch.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/__init__.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/bench_attn_compare.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/bench_iq2s_variants.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/bench_wave_prefill.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/debug_conv1d.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_aq2.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_bf16_numpy.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_compat.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_dequant_fp8.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_direct_fp8_quant.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_ffn_layer.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_fused_ssm_prefill.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_gemv_kquants.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_hq2.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_hq2_portable.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_hq8_g128.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_iq2s_iq1m_byte_exact.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_iquant_parallel.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_lazy_torch_import.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_mixed_policy.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_mixed_sensitivity.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_mxfp4_compat.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_mxfp4_native_contract.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_mxfp8_numerical.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_patch_hq_mixed_archive.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_pipeline.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_prefill_with_lse.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_q_to_fp8_gpu.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_qol.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_safetensors_numpy.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_v8.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_wave_attn_decode_hybrid.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_wave_prefill_gqa.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_wmma_diag.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/test_wmma_layout.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/bench_compare.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/bench_fp8.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/conftest.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/test_fp8.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/test_fp8_v2.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/test_hip_graph.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/test_mxfp4_native_contract_torch.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/test_mxfp4_to_fp8_torch.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/test_mxfp8_torch.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/test_q_to_fp8_torch.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/test_quant_transpose.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/torch/test_wave_attn_backward_math.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tests/verify_fused_fp8_linear.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tools/mlp_codec/analyze.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tools/mlp_codec/clean_wikitext.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tools/mlp_codec/collect_hessians.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tools/mlp_codec/hq2_bridge.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tools/mlp_codec/hq2v.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tools/mlp_codec/ldlq.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tools/mlp_codec/ledger.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tools/mlp_codec/run_ladder.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tools/mlp_codec/safe_run.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/tools/mlp_codec/validate_hessians.py +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/current_stream.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/dequant_q_to_fp16.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/fp8_linear_kernels_v2.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/fp8_quant_kernels.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/hq2_linear_kernels.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/hq3_linear_kernels.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/hq8_g128_linear_kernels.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/iq_grid_tables.h +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/kv_iu4_kernels.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/mxfp8_kernels.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/pytorch_bindings_hip.cpp +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/q_to_fp8_kernels.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/ssm_kernels.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/wave_attn_backward.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/wave_attn_common.h +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/wave_attn_decode.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/wave_attn_diag.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/torch_ext/wave_attn_prefill.hip +0 -0
- {hip_quant-2.2.0 → hip_quant-2.2.1}/wave_helpers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hip-quant
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: High-performance GPU tensor quantization and inference engine for AMD ROCm. Native AOT GEMV (K-Quants & I-Quants), State Space Model (SSM/DeltaNet) kernels, FP8 WMMA WaveAttention, and portable HIP C++ kernels for RDNA4, RDNA3, and CDNA.
|
|
5
5
|
Author-email: Thenukegun10x <conormorris84@gmail.com>
|
|
6
6
|
License: Apache License
|
|
@@ -219,6 +219,8 @@ License-File: LICENSE
|
|
|
219
219
|
Requires-Dist: numpy
|
|
220
220
|
Provides-Extra: torch
|
|
221
221
|
Requires-Dist: torch>=2.0; extra == "torch"
|
|
222
|
+
Provides-Extra: torch215
|
|
223
|
+
Requires-Dist: torch==2.15.0a0+gitf07882e; extra == "torch215"
|
|
222
224
|
Dynamic: license-file
|
|
223
225
|
|
|
224
226
|
<div align="center">
|
|
@@ -237,6 +239,18 @@ Dynamic: license-file
|
|
|
237
239
|
|
|
238
240
|
`hip-quant` is a standalone Python library and highly optimized HIP C++ backend for tensor quantization and accelerated LLM inference on AMD GPUs with zero CPU round-trips.
|
|
239
241
|
|
|
242
|
+
## 🌟 What's New in 2.2.1
|
|
243
|
+
|
|
244
|
+
> **2.2.1.post215** is the same release rebuilt against PyTorch 2.15 (TheRock / ROCm 7.14). See *Custom PyTorch 2.15* below for a self-hosted install index.
|
|
245
|
+
|
|
246
|
+
Security, correctness and robustness fixes from an internal audit:
|
|
247
|
+
|
|
248
|
+
- **Kernels**: fixed a missing CTA barrier in `wave_attn`/`wave_attn_long` (V overwrote the K tile while waves were still reading it), corrected the causal K-tile clamp (dropped the diagonal tile at exact boundaries), added `Dim <= 128` guards to the wave forward entry points, made the `gemv_tune` dispatch selector thread-local and exception-safe, and 64-bit-corrected FP8 GEMM index arithmetic.
|
|
249
|
+
- **Parsers (untrusted input)**: bounded GGUF string/array reads and the legacy HQ2 manifest (small crafted files could force multi-GiB allocations), rejected `general.alignment <= 0`, and replaced `assert`-based shape validation with explicit raises.
|
|
250
|
+
- **Offline API**: `quantize_from_fp8` now validates the `imatrix` element count (was a host + device out-of-bounds read), `ggml_blck_size_for` restype corrected, `math.prod` for element counts.
|
|
251
|
+
- **Hardening**: `_C` is loaded by absolute path (no `sys.path` mutation), `HIP_QUANT_DLL`/`_PATH` must be absolute, and the mxfp4 LUT init is `std::call_once`.
|
|
252
|
+
- **gpu-smi** is now fetched from its GitHub Releases at build time (checksum-verified) and bundled in the wheel; `smi.py` discovers it dynamically (env → bundled → console script → PATH) instead of hardcoding a path.
|
|
253
|
+
|
|
240
254
|
## 🌟 What's New in 2.2.0
|
|
241
255
|
|
|
242
256
|
> **2.2.0.post215** is the same release rebuilt against PyTorch 2.15 (TheRock / ROCm 7.14). Use it if `2.2.0` reports a torch ABI mismatch on import.
|
|
@@ -545,19 +559,55 @@ the next replay.
|
|
|
545
559
|
## 📦 Installation
|
|
546
560
|
|
|
547
561
|
```powershell
|
|
548
|
-
#
|
|
549
|
-
pip install
|
|
562
|
+
# From PyPI: binary wheel with the packaged ROCm 7.2.1 ctypes DLL and PyTorch extension
|
|
563
|
+
pip install hip-quant
|
|
550
564
|
|
|
551
|
-
# With PyTorch optional dependency declared
|
|
565
|
+
# With the PyTorch optional dependency declared
|
|
552
566
|
pip install "hip-quant[torch]"
|
|
567
|
+
|
|
568
|
+
# Or a local wheel
|
|
569
|
+
pip install dist/hip_quant-2.2.0-cp312-cp312-win_amd64.whl
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
Two wheels are published per release, one per PyTorch ABI. Install the one that
|
|
573
|
+
matches your PyTorch, so the extension loads without an ABI mismatch:
|
|
574
|
+
|
|
575
|
+
| Wheel | PyTorch | ROCm |
|
|
576
|
+
|---|---|---|
|
|
577
|
+
| `hip-quant==2.2.1` | 2.9.x | ROCm 7.2.1 |
|
|
578
|
+
| `hip-quant==2.2.1.post215` | 2.15 / TheRock | ROCm 7.14 |
|
|
579
|
+
|
|
580
|
+
```powershell
|
|
581
|
+
pip install "hip-quant==2.2.1.post215" # PyTorch 2.15 / TheRock
|
|
553
582
|
```
|
|
554
583
|
|
|
584
|
+
#### Custom PyTorch 2.15 (self-hosted wheels)
|
|
585
|
+
|
|
586
|
+
The `post215` wheel targets a custom PyTorch 2.15 build that is not on PyPI.
|
|
587
|
+
Its wheels live in a public Backblaze B2 bucket; point pip at the index page
|
|
588
|
+
with `--find-links`:
|
|
589
|
+
|
|
590
|
+
```powershell
|
|
591
|
+
pip install "hip-quant==2.2.1.post215" `
|
|
592
|
+
--find-links https://dl.hipquant.download/file/Torchs/torch_index.html
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
This resolves `torch==2.15.0a0+gitf07882e` (plus matching `torchvision` /
|
|
596
|
+
`torchaudio`). `gpu-smi` is bundled in the wheel, so monitoring needs no extra
|
|
597
|
+
step.
|
|
598
|
+
|
|
599
|
+
The wheels can also be fetched directly, e.g.
|
|
600
|
+
`https://dl.hipquant.download/file/Torchs/torch-2.15.0a0%2Bgitf07882e-cp312-cp312-win_amd64.whl`
|
|
601
|
+
— the `+` **must** be percent-encoded as `%2B` (a literal `+` 404s on B2).
|
|
602
|
+
Because wheel filenames must match their metadata version, the objects are
|
|
603
|
+
named `torch-2.15.0a0+gitf07882e-…`, not `torch-2.15.0-…`.
|
|
604
|
+
|
|
555
605
|
On Windows, DLL resolution order is:
|
|
556
606
|
- `HIP_QUANT_DLL` or `HIP_QUANT_DLL_PATH`, if set
|
|
557
607
|
- `hip_quantize_rocm721.dll`
|
|
558
608
|
- `hip_quantize.dll`
|
|
559
609
|
|
|
560
|
-
Runtime DLL directories include `HIP_QUANT_ROCM_BIN`, `HIP_QUANT_ROCM_HOME`, `ROCM_HOME`, `ROCM_PATH`, `HIP_PATH`, the active venv's `_rocm_sdk_core\bin`, `torch\lib`, `Scripts`, then the system ROCm 7.
|
|
610
|
+
Runtime DLL directories include `HIP_QUANT_ROCM_BIN`, `HIP_QUANT_ROCM_HOME`, `ROCM_HOME`, `ROCM_PATH`, `HIP_PATH`, the active venv's `_rocm_sdk_core\bin`, `torch\lib`, `Scripts`, then the system ROCm 7.2 path.
|
|
561
611
|
|
|
562
612
|
---
|
|
563
613
|
|
|
@@ -820,6 +870,20 @@ Block-wise scaling is useful when a tensor has uneven dynamic range across its
|
|
|
820
870
|
last dimension. It usually reduces FP8 quantization error compared with one
|
|
821
871
|
global scale for the entire tensor. Existing per-tensor FP8 APIs remain unchanged.
|
|
822
872
|
|
|
873
|
+
#### Dynamic Per-Token FP8 Quantization
|
|
874
|
+
|
|
875
|
+
`quantize_e4m3_per_token` computes a single FP32 dequant scale for an entire row
|
|
876
|
+
(`amax / 448`). This is the `activation_scheme: "dynamic"` used by
|
|
877
|
+
DeepSeek/vLLM FP8 checkpoints. For an input `[..., K]` the scale tensor has
|
|
878
|
+
shape `[...]` — one value per row:
|
|
879
|
+
|
|
880
|
+
```python
|
|
881
|
+
from hip_quant.torch_api import quantize_e4m3_per_token
|
|
882
|
+
|
|
883
|
+
x_fp8, x_scale = quantize_e4m3_per_token(x) # x_scale: [M], real ~= fp8 * scale[m]
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
|
|
823
887
|
#### Block-scaled Linear and Adafactor Kernel Helpers
|
|
824
888
|
|
|
825
889
|
Two lower-level training helpers are available for experiments and future fused
|
|
@@ -848,12 +912,51 @@ out = fp8_linear_forward_blockwise_quantized(
|
|
|
848
912
|
)
|
|
849
913
|
```
|
|
850
914
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
915
|
+
#### 2-D Block-Scaled FP8 Linear (vLLM / DeepSeek)
|
|
916
|
+
|
|
917
|
+
`fp8_linear_forward_blockwise_2d` consumes a safetensors `weight_scale_inv`
|
|
918
|
+
directly: a `[N, K]` E4M3 weight plus one dequant scale per `block x block`
|
|
919
|
+
tile (typically `128 x 128`), i.e. a `[N/block, K/block]` FP32 tensor, paired
|
|
920
|
+
with a single per-token activation scale `[M]`:
|
|
921
|
+
|
|
922
|
+
```text
|
|
923
|
+
C[m,n] = input_scale[m] * sum_kb W_scale[n/block, kb] * <A[m,:], B[n,:]>_kb
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
```python
|
|
927
|
+
from hip_quant import fp8_linear_forward_blockwise_2d, fp8_linear_deepseek
|
|
928
|
+
|
|
929
|
+
# From raw FP8 + 2-D scale tensors (already on device)
|
|
930
|
+
out = fp8_linear_forward_blockwise_2d(
|
|
931
|
+
input_fp8, input_scale, # quantize_e4m3_per_token(x)
|
|
932
|
+
weight_fp8, weight_scale_inv, # [N, K] uint8, [N/128, K/128] float32
|
|
933
|
+
output_dtype_source=x,
|
|
934
|
+
block_size=128, backend="auto", bias=bias,
|
|
935
|
+
)
|
|
936
|
+
|
|
937
|
+
# One-shot: dynamically quantizes x per token, then runs the fused GEMM
|
|
938
|
+
out = fp8_linear_deepseek(x, weight_fp8, weight_scale_inv, bias=bias)
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
`backend` selects the kernel at runtime:
|
|
942
|
+
|
|
943
|
+
| backend | kernel | notes |
|
|
944
|
+
|---|---|---|
|
|
945
|
+
| `"auto"` (default) | gfx12 WMMA when the shape allows, else portable | recommended |
|
|
946
|
+
| `"wmma"` | gfx12 `v_wmma_f32_16x16x16_fp8_fp8`, one weight-tile scale folded per 128-K stage | gfx12 only |
|
|
947
|
+
| `"portable"` | LDS-tiled `64x64x32` microkernel, exact fp8->fp16 shared-memory decode | any AMD GPU, no matrix intrinsics |
|
|
948
|
+
| `"reference"` | naive per-element kernel | slow; testing only |
|
|
949
|
+
|
|
950
|
+
The per-token activation scale is constant across K, so it is factored out of
|
|
951
|
+
the accumulation; only the weight tile scale is applied per 128-K block. Scales
|
|
952
|
+
are dequant scales (`real ~= fp8 * scale`), matching `weight_scale_inv`, so a
|
|
953
|
+
checkpoint can be fed verbatim with no re-quantization of the weights.
|
|
954
|
+
|
|
955
|
+
The 1-D `fp8_linear_forward_blockwise_quantized` kernel above is correctness-first
|
|
956
|
+
and does **not** use gfx12 WMMA; the 2-D path does (see the backend table).
|
|
957
|
+
`Adafactor` is a full Python optimizer step with factored second-moment state;
|
|
958
|
+
GPU-side row/column mean-square helpers exist, while a fully fused Adafactor
|
|
959
|
+
update kernel remains a future optimization.
|
|
857
960
|
|
|
858
961
|
#### Fake-FP8 Linear (autograd-safe, Phase 3)
|
|
859
962
|
|
|
@@ -964,6 +1067,9 @@ from hip_quant import (
|
|
|
964
1067
|
fp8_linear_forward_scaled,
|
|
965
1068
|
fp8_linear_forward_fp8_weight,
|
|
966
1069
|
fp8_linear_forward_blockwise,
|
|
1070
|
+
fp8_linear_forward_blockwise_quantized,
|
|
1071
|
+
fp8_linear_forward_blockwise_2d,
|
|
1072
|
+
fp8_linear_deepseek,
|
|
967
1073
|
fp8_linear_backward_input,
|
|
968
1074
|
fp8_linear_backward_input_scaled,
|
|
969
1075
|
fp8_linear_backward_weight,
|
|
@@ -983,6 +1089,9 @@ grad_wt_s = fp8_linear_backward_weight_scaled(grad_output, input, input_scale)
|
|
|
983
1089
|
|
|
984
1090
|
# Correctness-first block-scaled FP8 path, no WMMA requirement
|
|
985
1091
|
out_block = fp8_linear_forward_blockwise(input, weight, bias, block_size=32)
|
|
1092
|
+
|
|
1093
|
+
# 2-D (128x128 tile) block-scaled FP8 path from a safetensors weight_scale_inv
|
|
1094
|
+
out_2d = fp8_linear_deepseek(input, weight_fp8, weight_scale_inv, bias=bias)
|
|
986
1095
|
```
|
|
987
1096
|
|
|
988
1097
|
These functions are also used by `Fp8Linear`, `Fp8ScaledLinear`, and
|
|
@@ -1061,10 +1170,9 @@ All PyTorch extension functions are guarded against:
|
|
|
1061
1170
|
|
|
1062
1171
|
## 🧪 Running Tests
|
|
1063
1172
|
|
|
1064
|
-
####
|
|
1173
|
+
#### Extension FP8 tests (GPU required)
|
|
1065
1174
|
```powershell
|
|
1066
|
-
python tests/torch/
|
|
1067
|
-
# 90/90 pass — validated against ml_dtypes reference
|
|
1175
|
+
& "C:\venvs\medusa_rocm\Scripts\python.exe" -m pytest tests/torch/test_fp8.py -v
|
|
1068
1176
|
```
|
|
1069
1177
|
|
|
1070
1178
|
#### Full pipeline tests (CPU mock, no GPU required)
|
|
@@ -1128,20 +1236,27 @@ $env:HIP_QUANT_BUILD_TORCH_EXT = "1"
|
|
|
1128
1236
|
Check the artifacts:
|
|
1129
1237
|
```powershell
|
|
1130
1238
|
& "C:\venvs\medusa_rocm\Scripts\python.exe" -m twine check `
|
|
1131
|
-
"dist\hip_quant-
|
|
1132
|
-
"dist\hip_quant-
|
|
1239
|
+
"dist\hip_quant-2.2.0-cp312-cp312-win_amd64.whl" `
|
|
1240
|
+
"dist\hip_quant-2.2.0.tar.gz"
|
|
1133
1241
|
```
|
|
1134
1242
|
|
|
1135
1243
|
Upload to PyPI:
|
|
1136
1244
|
```powershell
|
|
1137
1245
|
& "C:\venvs\medusa_rocm\Scripts\python.exe" -m twine upload `
|
|
1138
|
-
"dist\hip_quant-
|
|
1139
|
-
"dist\hip_quant-
|
|
1246
|
+
"dist\hip_quant-2.2.0-cp312-cp312-win_amd64.whl" `
|
|
1247
|
+
"dist\hip_quant-2.2.0.tar.gz"
|
|
1140
1248
|
```
|
|
1141
1249
|
|
|
1142
|
-
Do not upload stale universal wheels such as `hip_quant-
|
|
1250
|
+
Do not upload stale universal wheels such as `hip_quant-2.2.0-py3-none-any.whl`.
|
|
1143
1251
|
The Windows wheel is intentionally platform-tagged because it contains DLLs.
|
|
1144
1252
|
|
|
1253
|
+
Each release publishes two versions from the same sources — `X.Y.Z` (PyTorch
|
|
1254
|
+
2.9.x / ROCm 7.2) and `X.Y.Z.post215` (PyTorch 2.15 / TheRock ROCm 7.14). Build
|
|
1255
|
+
each in its own venv: `setup_torch.py` picks the ROCm 7.14/TheRock toolchain for
|
|
1256
|
+
a `torch.version.hip` of `7.14.*` and `C:\Program Files\AMD\ROCm\<major.minor>`
|
|
1257
|
+
otherwise (see the toolchain matrix in `AGENTS.md`). Never build the 2.9.x
|
|
1258
|
+
artifact against TheRock, or vice versa.
|
|
1259
|
+
|
|
1145
1260
|
Suggested release order:
|
|
1146
1261
|
- Build and run `twine check`
|
|
1147
1262
|
- Upload to TestPyPI or PyPI
|
|
@@ -1154,9 +1269,13 @@ Suggested release order:
|
|
|
1154
1269
|
|
|
1155
1270
|
```
|
|
1156
1271
|
hip_quant/
|
|
1157
|
-
├── __init__.py # NumPy / ctypes offline API
|
|
1272
|
+
├── __init__.py # NumPy / ctypes offline API + lazy export table
|
|
1158
1273
|
├── __main__.py # CLI entry point
|
|
1159
|
-
├── torch_api.py # PyTorch FP8
|
|
1274
|
+
├── torch_api.py # PyTorch FP8 / GEMM / attention API (Phases 1-4)
|
|
1275
|
+
├── gguf.py # Pure-Python GGUF parser
|
|
1276
|
+
├── gguf_loader.py # Streaming GGUF -> VRAM tensor loader
|
|
1277
|
+
├── wave_helpers.py # Drop-in wave attention helpers
|
|
1278
|
+
├── smi.py # gpu-smi wrapper
|
|
1160
1279
|
├── device_info.py # GPU/DLL compatibility probe helpers
|
|
1161
1280
|
├── cdna_compat.py # CDNA feature table, build configs, CPU refs
|
|
1162
1281
|
├── setup_torch.py # PyTorch C++ extension build script
|
|
@@ -1167,17 +1286,23 @@ hip_quant/
|
|
|
1167
1286
|
├── kernels/ # Per-format offline HIP kernels (.cu)
|
|
1168
1287
|
├── torch_ext/ # PyTorch extension source
|
|
1169
1288
|
│ ├── pytorch_bindings.cpp # C++ bindings (TORCH_CHECK, pybind11)
|
|
1170
|
-
│ ├── fp8_quant_kernels.hip# Element-wise quant
|
|
1171
|
-
│ ├──
|
|
1172
|
-
│
|
|
1173
|
-
|
|
1289
|
+
│ ├── fp8_quant_kernels.hip # Element-wise + per-token + block-wise quant
|
|
1290
|
+
│ ├── fp8_linear_kernels.hip # FP8 GEMM: naive + tiled portable + 2-D block scales
|
|
1291
|
+
│ ├── fp8_linear_kernels_v2.hip # gfx12 LDS-staged FP8 WMMA GEMM (incl. 2-D block scales)
|
|
1292
|
+
│ ├── mxfp8_kernels.hip # MXFP8 UE8M0 quant/dequant (OCP, 32-thread warp)
|
|
1293
|
+
│ ├── gemv_q_kernels.hip # GGUF AOT GEMV (K-/I-quants)
|
|
1294
|
+
│ ├── hq2_linear_kernels.hip # HQ2 learned-codebook formats
|
|
1295
|
+
│ ├── hq3_linear_kernels.hip # HQ3 learned-codebook formats
|
|
1296
|
+
│ ├── ssm_kernels.hip # SSM / DeltaNet / fused norms
|
|
1297
|
+
│ └── wave_attn*.hip # WaveAttention FP8 WMMA prefill/decode/backward
|
|
1298
|
+
└── tests/ # pytest suite (CPU pipeline in tests/test_pipeline.py)
|
|
1174
1299
|
```
|
|
1175
1300
|
|
|
1176
1301
|
---
|
|
1177
1302
|
|
|
1178
1303
|
## 📋 Architecture Notes
|
|
1179
1304
|
|
|
1180
|
-
- **RDNA4 PyTorch target** —
|
|
1305
|
+
- **RDNA4 PyTorch target** — release `_C` builds are a multi-arch fatbin for `gfx90a`, `gfx942`, RDNA3 `gfx1100`-`gfx1103`, and RDNA4 `gfx1200`/`gfx1201` (`HIP_QUANT_ARCH` overrides this; a `gfx1201`-only build is the fast local-dev option). The gfx12 FP8 WMMA kernels require a `gfx1200`/`gfx1201` device at runtime.
|
|
1181
1306
|
- **Default offline DLL target** — `build.ps1` compiles the portable DLL quantization kernels for `gfx90a`, `gfx942`, RDNA3 `gfx1100`-`gfx1103`, and RDNA4 `gfx1200`/`gfx1201`
|
|
1182
1307
|
- **Current validation scope** — runtime-tested locally on `gfx1201` RX 9070 XT; `gfx1200` and CDNA code objects are build-validated and need separate hardware runtime validation
|
|
1183
1308
|
- **BF16/FP16 PyTorch support** — FP8 quantization and linear kernels accept FP32, FP16, and BF16 tensors, accumulating in FP32 registers and storing results in the input/master dtype
|
|
@@ -14,6 +14,18 @@
|
|
|
14
14
|
|
|
15
15
|
`hip-quant` is a standalone Python library and highly optimized HIP C++ backend for tensor quantization and accelerated LLM inference on AMD GPUs with zero CPU round-trips.
|
|
16
16
|
|
|
17
|
+
## 🌟 What's New in 2.2.1
|
|
18
|
+
|
|
19
|
+
> **2.2.1.post215** is the same release rebuilt against PyTorch 2.15 (TheRock / ROCm 7.14). See *Custom PyTorch 2.15* below for a self-hosted install index.
|
|
20
|
+
|
|
21
|
+
Security, correctness and robustness fixes from an internal audit:
|
|
22
|
+
|
|
23
|
+
- **Kernels**: fixed a missing CTA barrier in `wave_attn`/`wave_attn_long` (V overwrote the K tile while waves were still reading it), corrected the causal K-tile clamp (dropped the diagonal tile at exact boundaries), added `Dim <= 128` guards to the wave forward entry points, made the `gemv_tune` dispatch selector thread-local and exception-safe, and 64-bit-corrected FP8 GEMM index arithmetic.
|
|
24
|
+
- **Parsers (untrusted input)**: bounded GGUF string/array reads and the legacy HQ2 manifest (small crafted files could force multi-GiB allocations), rejected `general.alignment <= 0`, and replaced `assert`-based shape validation with explicit raises.
|
|
25
|
+
- **Offline API**: `quantize_from_fp8` now validates the `imatrix` element count (was a host + device out-of-bounds read), `ggml_blck_size_for` restype corrected, `math.prod` for element counts.
|
|
26
|
+
- **Hardening**: `_C` is loaded by absolute path (no `sys.path` mutation), `HIP_QUANT_DLL`/`_PATH` must be absolute, and the mxfp4 LUT init is `std::call_once`.
|
|
27
|
+
- **gpu-smi** is now fetched from its GitHub Releases at build time (checksum-verified) and bundled in the wheel; `smi.py` discovers it dynamically (env → bundled → console script → PATH) instead of hardcoding a path.
|
|
28
|
+
|
|
17
29
|
## 🌟 What's New in 2.2.0
|
|
18
30
|
|
|
19
31
|
> **2.2.0.post215** is the same release rebuilt against PyTorch 2.15 (TheRock / ROCm 7.14). Use it if `2.2.0` reports a torch ABI mismatch on import.
|
|
@@ -322,19 +334,55 @@ the next replay.
|
|
|
322
334
|
## 📦 Installation
|
|
323
335
|
|
|
324
336
|
```powershell
|
|
325
|
-
#
|
|
326
|
-
pip install
|
|
337
|
+
# From PyPI: binary wheel with the packaged ROCm 7.2.1 ctypes DLL and PyTorch extension
|
|
338
|
+
pip install hip-quant
|
|
327
339
|
|
|
328
|
-
# With PyTorch optional dependency declared
|
|
340
|
+
# With the PyTorch optional dependency declared
|
|
329
341
|
pip install "hip-quant[torch]"
|
|
342
|
+
|
|
343
|
+
# Or a local wheel
|
|
344
|
+
pip install dist/hip_quant-2.2.0-cp312-cp312-win_amd64.whl
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Two wheels are published per release, one per PyTorch ABI. Install the one that
|
|
348
|
+
matches your PyTorch, so the extension loads without an ABI mismatch:
|
|
349
|
+
|
|
350
|
+
| Wheel | PyTorch | ROCm |
|
|
351
|
+
|---|---|---|
|
|
352
|
+
| `hip-quant==2.2.1` | 2.9.x | ROCm 7.2.1 |
|
|
353
|
+
| `hip-quant==2.2.1.post215` | 2.15 / TheRock | ROCm 7.14 |
|
|
354
|
+
|
|
355
|
+
```powershell
|
|
356
|
+
pip install "hip-quant==2.2.1.post215" # PyTorch 2.15 / TheRock
|
|
330
357
|
```
|
|
331
358
|
|
|
359
|
+
#### Custom PyTorch 2.15 (self-hosted wheels)
|
|
360
|
+
|
|
361
|
+
The `post215` wheel targets a custom PyTorch 2.15 build that is not on PyPI.
|
|
362
|
+
Its wheels live in a public Backblaze B2 bucket; point pip at the index page
|
|
363
|
+
with `--find-links`:
|
|
364
|
+
|
|
365
|
+
```powershell
|
|
366
|
+
pip install "hip-quant==2.2.1.post215" `
|
|
367
|
+
--find-links https://dl.hipquant.download/file/Torchs/torch_index.html
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
This resolves `torch==2.15.0a0+gitf07882e` (plus matching `torchvision` /
|
|
371
|
+
`torchaudio`). `gpu-smi` is bundled in the wheel, so monitoring needs no extra
|
|
372
|
+
step.
|
|
373
|
+
|
|
374
|
+
The wheels can also be fetched directly, e.g.
|
|
375
|
+
`https://dl.hipquant.download/file/Torchs/torch-2.15.0a0%2Bgitf07882e-cp312-cp312-win_amd64.whl`
|
|
376
|
+
— the `+` **must** be percent-encoded as `%2B` (a literal `+` 404s on B2).
|
|
377
|
+
Because wheel filenames must match their metadata version, the objects are
|
|
378
|
+
named `torch-2.15.0a0+gitf07882e-…`, not `torch-2.15.0-…`.
|
|
379
|
+
|
|
332
380
|
On Windows, DLL resolution order is:
|
|
333
381
|
- `HIP_QUANT_DLL` or `HIP_QUANT_DLL_PATH`, if set
|
|
334
382
|
- `hip_quantize_rocm721.dll`
|
|
335
383
|
- `hip_quantize.dll`
|
|
336
384
|
|
|
337
|
-
Runtime DLL directories include `HIP_QUANT_ROCM_BIN`, `HIP_QUANT_ROCM_HOME`, `ROCM_HOME`, `ROCM_PATH`, `HIP_PATH`, the active venv's `_rocm_sdk_core\bin`, `torch\lib`, `Scripts`, then the system ROCm 7.
|
|
385
|
+
Runtime DLL directories include `HIP_QUANT_ROCM_BIN`, `HIP_QUANT_ROCM_HOME`, `ROCM_HOME`, `ROCM_PATH`, `HIP_PATH`, the active venv's `_rocm_sdk_core\bin`, `torch\lib`, `Scripts`, then the system ROCm 7.2 path.
|
|
338
386
|
|
|
339
387
|
---
|
|
340
388
|
|
|
@@ -597,6 +645,20 @@ Block-wise scaling is useful when a tensor has uneven dynamic range across its
|
|
|
597
645
|
last dimension. It usually reduces FP8 quantization error compared with one
|
|
598
646
|
global scale for the entire tensor. Existing per-tensor FP8 APIs remain unchanged.
|
|
599
647
|
|
|
648
|
+
#### Dynamic Per-Token FP8 Quantization
|
|
649
|
+
|
|
650
|
+
`quantize_e4m3_per_token` computes a single FP32 dequant scale for an entire row
|
|
651
|
+
(`amax / 448`). This is the `activation_scheme: "dynamic"` used by
|
|
652
|
+
DeepSeek/vLLM FP8 checkpoints. For an input `[..., K]` the scale tensor has
|
|
653
|
+
shape `[...]` — one value per row:
|
|
654
|
+
|
|
655
|
+
```python
|
|
656
|
+
from hip_quant.torch_api import quantize_e4m3_per_token
|
|
657
|
+
|
|
658
|
+
x_fp8, x_scale = quantize_e4m3_per_token(x) # x_scale: [M], real ~= fp8 * scale[m]
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
|
|
600
662
|
#### Block-scaled Linear and Adafactor Kernel Helpers
|
|
601
663
|
|
|
602
664
|
Two lower-level training helpers are available for experiments and future fused
|
|
@@ -625,12 +687,51 @@ out = fp8_linear_forward_blockwise_quantized(
|
|
|
625
687
|
)
|
|
626
688
|
```
|
|
627
689
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
690
|
+
#### 2-D Block-Scaled FP8 Linear (vLLM / DeepSeek)
|
|
691
|
+
|
|
692
|
+
`fp8_linear_forward_blockwise_2d` consumes a safetensors `weight_scale_inv`
|
|
693
|
+
directly: a `[N, K]` E4M3 weight plus one dequant scale per `block x block`
|
|
694
|
+
tile (typically `128 x 128`), i.e. a `[N/block, K/block]` FP32 tensor, paired
|
|
695
|
+
with a single per-token activation scale `[M]`:
|
|
696
|
+
|
|
697
|
+
```text
|
|
698
|
+
C[m,n] = input_scale[m] * sum_kb W_scale[n/block, kb] * <A[m,:], B[n,:]>_kb
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
```python
|
|
702
|
+
from hip_quant import fp8_linear_forward_blockwise_2d, fp8_linear_deepseek
|
|
703
|
+
|
|
704
|
+
# From raw FP8 + 2-D scale tensors (already on device)
|
|
705
|
+
out = fp8_linear_forward_blockwise_2d(
|
|
706
|
+
input_fp8, input_scale, # quantize_e4m3_per_token(x)
|
|
707
|
+
weight_fp8, weight_scale_inv, # [N, K] uint8, [N/128, K/128] float32
|
|
708
|
+
output_dtype_source=x,
|
|
709
|
+
block_size=128, backend="auto", bias=bias,
|
|
710
|
+
)
|
|
711
|
+
|
|
712
|
+
# One-shot: dynamically quantizes x per token, then runs the fused GEMM
|
|
713
|
+
out = fp8_linear_deepseek(x, weight_fp8, weight_scale_inv, bias=bias)
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
`backend` selects the kernel at runtime:
|
|
717
|
+
|
|
718
|
+
| backend | kernel | notes |
|
|
719
|
+
|---|---|---|
|
|
720
|
+
| `"auto"` (default) | gfx12 WMMA when the shape allows, else portable | recommended |
|
|
721
|
+
| `"wmma"` | gfx12 `v_wmma_f32_16x16x16_fp8_fp8`, one weight-tile scale folded per 128-K stage | gfx12 only |
|
|
722
|
+
| `"portable"` | LDS-tiled `64x64x32` microkernel, exact fp8->fp16 shared-memory decode | any AMD GPU, no matrix intrinsics |
|
|
723
|
+
| `"reference"` | naive per-element kernel | slow; testing only |
|
|
724
|
+
|
|
725
|
+
The per-token activation scale is constant across K, so it is factored out of
|
|
726
|
+
the accumulation; only the weight tile scale is applied per 128-K block. Scales
|
|
727
|
+
are dequant scales (`real ~= fp8 * scale`), matching `weight_scale_inv`, so a
|
|
728
|
+
checkpoint can be fed verbatim with no re-quantization of the weights.
|
|
729
|
+
|
|
730
|
+
The 1-D `fp8_linear_forward_blockwise_quantized` kernel above is correctness-first
|
|
731
|
+
and does **not** use gfx12 WMMA; the 2-D path does (see the backend table).
|
|
732
|
+
`Adafactor` is a full Python optimizer step with factored second-moment state;
|
|
733
|
+
GPU-side row/column mean-square helpers exist, while a fully fused Adafactor
|
|
734
|
+
update kernel remains a future optimization.
|
|
634
735
|
|
|
635
736
|
#### Fake-FP8 Linear (autograd-safe, Phase 3)
|
|
636
737
|
|
|
@@ -741,6 +842,9 @@ from hip_quant import (
|
|
|
741
842
|
fp8_linear_forward_scaled,
|
|
742
843
|
fp8_linear_forward_fp8_weight,
|
|
743
844
|
fp8_linear_forward_blockwise,
|
|
845
|
+
fp8_linear_forward_blockwise_quantized,
|
|
846
|
+
fp8_linear_forward_blockwise_2d,
|
|
847
|
+
fp8_linear_deepseek,
|
|
744
848
|
fp8_linear_backward_input,
|
|
745
849
|
fp8_linear_backward_input_scaled,
|
|
746
850
|
fp8_linear_backward_weight,
|
|
@@ -760,6 +864,9 @@ grad_wt_s = fp8_linear_backward_weight_scaled(grad_output, input, input_scale)
|
|
|
760
864
|
|
|
761
865
|
# Correctness-first block-scaled FP8 path, no WMMA requirement
|
|
762
866
|
out_block = fp8_linear_forward_blockwise(input, weight, bias, block_size=32)
|
|
867
|
+
|
|
868
|
+
# 2-D (128x128 tile) block-scaled FP8 path from a safetensors weight_scale_inv
|
|
869
|
+
out_2d = fp8_linear_deepseek(input, weight_fp8, weight_scale_inv, bias=bias)
|
|
763
870
|
```
|
|
764
871
|
|
|
765
872
|
These functions are also used by `Fp8Linear`, `Fp8ScaledLinear`, and
|
|
@@ -838,10 +945,9 @@ All PyTorch extension functions are guarded against:
|
|
|
838
945
|
|
|
839
946
|
## 🧪 Running Tests
|
|
840
947
|
|
|
841
|
-
####
|
|
948
|
+
#### Extension FP8 tests (GPU required)
|
|
842
949
|
```powershell
|
|
843
|
-
python tests/torch/
|
|
844
|
-
# 90/90 pass — validated against ml_dtypes reference
|
|
950
|
+
& "C:\venvs\medusa_rocm\Scripts\python.exe" -m pytest tests/torch/test_fp8.py -v
|
|
845
951
|
```
|
|
846
952
|
|
|
847
953
|
#### Full pipeline tests (CPU mock, no GPU required)
|
|
@@ -905,20 +1011,27 @@ $env:HIP_QUANT_BUILD_TORCH_EXT = "1"
|
|
|
905
1011
|
Check the artifacts:
|
|
906
1012
|
```powershell
|
|
907
1013
|
& "C:\venvs\medusa_rocm\Scripts\python.exe" -m twine check `
|
|
908
|
-
"dist\hip_quant-
|
|
909
|
-
"dist\hip_quant-
|
|
1014
|
+
"dist\hip_quant-2.2.0-cp312-cp312-win_amd64.whl" `
|
|
1015
|
+
"dist\hip_quant-2.2.0.tar.gz"
|
|
910
1016
|
```
|
|
911
1017
|
|
|
912
1018
|
Upload to PyPI:
|
|
913
1019
|
```powershell
|
|
914
1020
|
& "C:\venvs\medusa_rocm\Scripts\python.exe" -m twine upload `
|
|
915
|
-
"dist\hip_quant-
|
|
916
|
-
"dist\hip_quant-
|
|
1021
|
+
"dist\hip_quant-2.2.0-cp312-cp312-win_amd64.whl" `
|
|
1022
|
+
"dist\hip_quant-2.2.0.tar.gz"
|
|
917
1023
|
```
|
|
918
1024
|
|
|
919
|
-
Do not upload stale universal wheels such as `hip_quant-
|
|
1025
|
+
Do not upload stale universal wheels such as `hip_quant-2.2.0-py3-none-any.whl`.
|
|
920
1026
|
The Windows wheel is intentionally platform-tagged because it contains DLLs.
|
|
921
1027
|
|
|
1028
|
+
Each release publishes two versions from the same sources — `X.Y.Z` (PyTorch
|
|
1029
|
+
2.9.x / ROCm 7.2) and `X.Y.Z.post215` (PyTorch 2.15 / TheRock ROCm 7.14). Build
|
|
1030
|
+
each in its own venv: `setup_torch.py` picks the ROCm 7.14/TheRock toolchain for
|
|
1031
|
+
a `torch.version.hip` of `7.14.*` and `C:\Program Files\AMD\ROCm\<major.minor>`
|
|
1032
|
+
otherwise (see the toolchain matrix in `AGENTS.md`). Never build the 2.9.x
|
|
1033
|
+
artifact against TheRock, or vice versa.
|
|
1034
|
+
|
|
922
1035
|
Suggested release order:
|
|
923
1036
|
- Build and run `twine check`
|
|
924
1037
|
- Upload to TestPyPI or PyPI
|
|
@@ -931,9 +1044,13 @@ Suggested release order:
|
|
|
931
1044
|
|
|
932
1045
|
```
|
|
933
1046
|
hip_quant/
|
|
934
|
-
├── __init__.py # NumPy / ctypes offline API
|
|
1047
|
+
├── __init__.py # NumPy / ctypes offline API + lazy export table
|
|
935
1048
|
├── __main__.py # CLI entry point
|
|
936
|
-
├── torch_api.py # PyTorch FP8
|
|
1049
|
+
├── torch_api.py # PyTorch FP8 / GEMM / attention API (Phases 1-4)
|
|
1050
|
+
├── gguf.py # Pure-Python GGUF parser
|
|
1051
|
+
├── gguf_loader.py # Streaming GGUF -> VRAM tensor loader
|
|
1052
|
+
├── wave_helpers.py # Drop-in wave attention helpers
|
|
1053
|
+
├── smi.py # gpu-smi wrapper
|
|
937
1054
|
├── device_info.py # GPU/DLL compatibility probe helpers
|
|
938
1055
|
├── cdna_compat.py # CDNA feature table, build configs, CPU refs
|
|
939
1056
|
├── setup_torch.py # PyTorch C++ extension build script
|
|
@@ -944,17 +1061,23 @@ hip_quant/
|
|
|
944
1061
|
├── kernels/ # Per-format offline HIP kernels (.cu)
|
|
945
1062
|
├── torch_ext/ # PyTorch extension source
|
|
946
1063
|
│ ├── pytorch_bindings.cpp # C++ bindings (TORCH_CHECK, pybind11)
|
|
947
|
-
│ ├── fp8_quant_kernels.hip# Element-wise quant
|
|
948
|
-
│ ├──
|
|
949
|
-
│
|
|
950
|
-
|
|
1064
|
+
│ ├── fp8_quant_kernels.hip # Element-wise + per-token + block-wise quant
|
|
1065
|
+
│ ├── fp8_linear_kernels.hip # FP8 GEMM: naive + tiled portable + 2-D block scales
|
|
1066
|
+
│ ├── fp8_linear_kernels_v2.hip # gfx12 LDS-staged FP8 WMMA GEMM (incl. 2-D block scales)
|
|
1067
|
+
│ ├── mxfp8_kernels.hip # MXFP8 UE8M0 quant/dequant (OCP, 32-thread warp)
|
|
1068
|
+
│ ├── gemv_q_kernels.hip # GGUF AOT GEMV (K-/I-quants)
|
|
1069
|
+
│ ├── hq2_linear_kernels.hip # HQ2 learned-codebook formats
|
|
1070
|
+
│ ├── hq3_linear_kernels.hip # HQ3 learned-codebook formats
|
|
1071
|
+
│ ├── ssm_kernels.hip # SSM / DeltaNet / fused norms
|
|
1072
|
+
│ └── wave_attn*.hip # WaveAttention FP8 WMMA prefill/decode/backward
|
|
1073
|
+
└── tests/ # pytest suite (CPU pipeline in tests/test_pipeline.py)
|
|
951
1074
|
```
|
|
952
1075
|
|
|
953
1076
|
---
|
|
954
1077
|
|
|
955
1078
|
## 📋 Architecture Notes
|
|
956
1079
|
|
|
957
|
-
- **RDNA4 PyTorch target** —
|
|
1080
|
+
- **RDNA4 PyTorch target** — release `_C` builds are a multi-arch fatbin for `gfx90a`, `gfx942`, RDNA3 `gfx1100`-`gfx1103`, and RDNA4 `gfx1200`/`gfx1201` (`HIP_QUANT_ARCH` overrides this; a `gfx1201`-only build is the fast local-dev option). The gfx12 FP8 WMMA kernels require a `gfx1200`/`gfx1201` device at runtime.
|
|
958
1081
|
- **Default offline DLL target** — `build.ps1` compiles the portable DLL quantization kernels for `gfx90a`, `gfx942`, RDNA3 `gfx1100`-`gfx1103`, and RDNA4 `gfx1200`/`gfx1201`
|
|
959
1082
|
- **Current validation scope** — runtime-tested locally on `gfx1201` RX 9070 XT; `gfx1200` and CDNA code objects are build-validated and need separate hardware runtime validation
|
|
960
1083
|
- **BF16/FP16 PyTorch support** — FP8 quantization and linear kernels accept FP32, FP16, and BF16 tensors, accumulating in FP32 registers and storing results in the input/master dtype
|
|
Binary file
|
|
@@ -3,7 +3,7 @@ import numpy as np
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
5
|
|
|
6
|
-
__version__ = "2.2.
|
|
6
|
+
__version__ = "2.2.1"
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
_TORCH_EXPORTS = {
|
|
@@ -284,6 +284,13 @@ def _add_runtime_dll_dirs():
|
|
|
284
284
|
def _shared_library_candidates():
|
|
285
285
|
env_dll = os.environ.get("HIP_QUANT_DLL") or os.environ.get("HIP_QUANT_DLL_PATH")
|
|
286
286
|
if env_dll:
|
|
287
|
+
# Only an absolute override is safe: a bare/relative name is resolved
|
|
288
|
+
# against the process CWD and can be shadowed by an attacker (DLL hijack).
|
|
289
|
+
if not os.path.isabs(env_dll):
|
|
290
|
+
raise ValueError(
|
|
291
|
+
"HIP_QUANT_DLL / HIP_QUANT_DLL_PATH must be an absolute path, got "
|
|
292
|
+
f"{env_dll!r}"
|
|
293
|
+
)
|
|
287
294
|
yield env_dll
|
|
288
295
|
|
|
289
296
|
win_names = ["hip_quantize_rocm721.dll", "hip_quantize.dll"]
|
|
@@ -389,7 +396,7 @@ class HipQuant:
|
|
|
389
396
|
self._dequantize_tensor_to_fp8 = None
|
|
390
397
|
self._dll.ggml_type_size_for.restype = ctypes.c_size_t
|
|
391
398
|
self._dll.ggml_type_size_for.argtypes = [ctypes.c_int]
|
|
392
|
-
self._dll.ggml_blck_size_for.restype = ctypes.
|
|
399
|
+
self._dll.ggml_blck_size_for.restype = ctypes.c_int
|
|
393
400
|
self._dll.ggml_blck_size_for.argtypes = [ctypes.c_int]
|
|
394
401
|
self._dll.ggml_row_size_for.restype = ctypes.c_size_t
|
|
395
402
|
self._dll.ggml_row_size_for.argtypes = [ctypes.c_int, ctypes.c_int64]
|
|
@@ -855,6 +862,16 @@ class HipQuant:
|
|
|
855
862
|
im_ptr = None
|
|
856
863
|
if imatrix is not None:
|
|
857
864
|
imatrix = np.ascontiguousarray(imatrix, dtype=np.float32)
|
|
865
|
+
# The native kernel indexes imatrix + row*n_per_row for every row,
|
|
866
|
+
# i.e. it reads exactly arr_fp8.size floats. Require at least that
|
|
867
|
+
# many (a short buffer is a host hipMemcpy + device OOB read), then
|
|
868
|
+
# reshape so the row indexing is well defined.
|
|
869
|
+
if imatrix.size != arr_fp8.size:
|
|
870
|
+
raise ValueError(
|
|
871
|
+
f"imatrix has {imatrix.size} elements but FP8 input has "
|
|
872
|
+
f"{arr_fp8.size} ({arr_fp8.shape})"
|
|
873
|
+
)
|
|
874
|
+
imatrix = imatrix.reshape(arr_fp8.shape)
|
|
858
875
|
im_ptr = imatrix.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
859
876
|
if isinstance(source_format, str):
|
|
860
877
|
source_format = source_format.upper()
|