hip-quant 2.2.3__tar.gz → 2.2.4__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.3 → hip_quant-2.2.4}/MANIFEST.in +3 -1
- {hip_quant-2.2.3/hip_quant.egg-info → hip_quant-2.2.4}/PKG-INFO +68 -32
- {hip_quant-2.2.3 → hip_quant-2.2.4}/README.md +67 -31
- hip_quant-2.2.4/_C.cp312-win_amd64.pyd +4 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/__init__.py +78 -47
- hip_quant-2.2.4/gguf.py +660 -0
- hip_quant-2.2.4/gguf_loader.py +687 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4/hip_quant.egg-info}/PKG-INFO +68 -32
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/SOURCES.txt +24 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quantize.cpp +11 -2
- hip_quant-2.2.4/hip_quantize_rocm721.dll +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/pyproject.toml +10 -2
- {hip_quant-2.2.3 → hip_quant-2.2.4}/setup_torch.py +7 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_iquant_parallel.py +0 -3
- hip_quant-2.2.4/tests/test_ssm_heads_generic.py +92 -0
- hip_quant-2.2.4/tests/torch/test_wave_attn_train_bf16.py +281 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_api.py +1090 -49
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/dequant_q_to_fp16.hip +19 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/fp8_linear_kernels_v2.hip +349 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/fp8_quant_kernels.hip +132 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/gemv_q_kernels.hip +202 -6
- hip_quant-2.2.4/torch_ext/hqnat_grouped_integer.hip +630 -0
- hip_quant-2.2.4/torch_ext/int3_g32_kernels.hip +663 -0
- hip_quant-2.2.4/torch_ext/int4_wmma_kernels.hip +417 -0
- hip_quant-2.2.4/torch_ext/int5_g32_kernels.hip +117 -0
- hip_quant-2.2.4/torch_ext/int6_g32_kernels.hip +118 -0
- hip_quant-2.2.4/torch_ext/lfm2_moe_int3_wmma.hip +281 -0
- hip_quant-2.2.4/torch_ext/ple_io.cpp +207 -0
- hip_quant-2.2.4/torch_ext/ple_io.h +49 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/pytorch_bindings.cpp +1396 -64
- hip_quant-2.2.4/torch_ext/qad_scale_gradient.hip +126 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/ssm_kernels.hip +53 -41
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/ternary_gemv_kernels.hip +47 -63
- hip_quant-2.2.4/torch_ext/wave_attn_backward_bf16.hip +703 -0
- hip_quant-2.2.4/torch_ext/wave_attn_backward_mx.hip +680 -0
- hip_quant-2.2.4/torch_ext/wave_attn_bf16.hip +666 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wht_kernels.hip +123 -26
- {hip_quant-2.2.3 → hip_quant-2.2.4}/wave_attn_train_strided_triton.py +4 -4
- {hip_quant-2.2.3 → hip_quant-2.2.4}/wave_attn_train_triton.py +4 -4
- hip_quant-2.2.3/_C.cp312-win_amd64.pyd +0 -4
- hip_quant-2.2.3/gguf.py +0 -303
- hip_quant-2.2.3/gguf_loader.py +0 -112
- hip_quant-2.2.3/hip_quantize_rocm721.dll +0 -0
- hip_quant-2.2.3/tests/torch/test_wave_attn_train_bf16.py +0 -101
- hip_quant-2.2.3/torch_ext/int4_wmma_kernels.hip +0 -168
- {hip_quant-2.2.3 → hip_quant-2.2.4}/DOCUMENTATION.md +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/LICENSE +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/__main__.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/bench_mxfp8.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/bench_wave_attn_inference.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/build.ps1 +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/build.sh +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/cdna_compat.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq1_s.bin +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq2_s.bin +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq2_xs.bin +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq2_xxs.bin +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq3_s.bin +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq3_xxs.bin +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/demo.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/device_info.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/diagnose_fp8_crash.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/e2e_iq2s_iq1m.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/get_hf_tensors.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_iquant_util.h +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/dependency_links.txt +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/entry_points.txt +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/not-zip-safe +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/requires.txt +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/top_level.txt +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant_types.h +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant_util.h +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quantize.dll +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/__init__.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/__main__.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/analyzer.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/api.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/archive.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/backends.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/format.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/hq3.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/hq8.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/mixed_policy.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/raw.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/safetensors_numpy.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/sensitivity.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/torch_inference.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/transformers_loader.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/dequant_to_fp8.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/direct_fp8_quant.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/fp8_expand.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/fp8_gemm_test.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_aq2.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_bf16.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_f8_e4m3.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_f8_e5m2.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_hq2.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq1_m.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq1_s.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq2_s.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq2_xs.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq2_xxs.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq3_s.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq3_xxs.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq4_nl.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq4_xs.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q1_0.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q2_0.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q2_K.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q3_K.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q4_0.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q4_1.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q4_K.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q5_0.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q5_1.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q5_K.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q6_K.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q8_0.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q8_1.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q8_K.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_tq1_0.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_tq2_0.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/wmma_diag.cu +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/setup.cfg +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/setup.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/smi.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/__init__.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/bench_attn_compare.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/bench_iq2s_variants.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/bench_wave_prefill.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/debug_conv1d.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_aq2.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_bf16_numpy.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_compat.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_dequant_fp8.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_direct_fp8_quant.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_ffn_layer.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_fused_ssm_prefill.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_gemv_kquants.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_hq2.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_hq2_portable.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_hq8_g128.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_iq2s_iq1m_byte_exact.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_lazy_torch_import.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_mixed_policy.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_mixed_sensitivity.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_mxfp4_compat.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_mxfp4_native_contract.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_mxfp8_numerical.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_patch_hq_mixed_archive.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_pipeline.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_prefill_with_lse.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_q_to_fp8_gpu.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_qol.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_safetensors_numpy.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_v8.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_wave_attn_decode_hybrid.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_wave_prefill_gqa.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_wmma_diag.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_wmma_layout.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/bench_compare.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/bench_fp8.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/conftest.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_fp8.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_fp8_v2.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_hip_graph.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_mxfp4_native_contract_torch.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_mxfp4_to_fp8_torch.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_mxfp8_torch.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_q_to_fp8_torch.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_quant_transpose.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_wave_attn_backward_math.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_wave_attn_f16.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_wave_attn_f16_extreme.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_wave_helpers_cpu.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/verify_fused_fp8_linear.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/.gpu-smi-version +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/fetch_gpu_smi.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/gpu-smi.exe +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/analyze.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/clean_wikitext.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/collect_hessians.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/hq2_bridge.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/hq2v.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/ldlq.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/ledger.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/run_ladder.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/safe_run.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/validate_hessians.py +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/current_stream.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/decode_quant_kernels.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/fp8_linear_kernels.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/hq2_linear_kernels.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/hq3_linear_kernels.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/hq8_g128_linear_kernels.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/iq_grid_tables.h +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/kv_iu4_kernels.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/mxfp4_to_fp8_kernels.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/mxfp8_kernels.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/pytorch_bindings_hip.cpp +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/q_to_fp8_kernels.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/w4a16_gemv_kernels.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_backward.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_backward_f16.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_common.h +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_decode.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_diag.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_f16.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_long.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_prefill.hip +0 -0
- {hip_quant-2.2.3 → hip_quant-2.2.4}/wave_helpers.py +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
include hip_quantize.dll
|
|
2
2
|
include hip_quantize_rocm721.dll
|
|
3
|
-
include _C*.pyd
|
|
4
3
|
include _C.cp312-win_amd64.pyd
|
|
5
4
|
include hip_quant_types.h
|
|
6
5
|
include hip_quant_util.h
|
|
@@ -10,6 +9,9 @@ include build.ps1
|
|
|
10
9
|
include build.sh
|
|
11
10
|
recursive-include kernels *.cu
|
|
12
11
|
recursive-include torch_ext *.cpp *.hip *.h
|
|
12
|
+
exclude torch_ext/ple_directstorage.cpp
|
|
13
|
+
exclude torch_ext/ple_directstorage.h
|
|
14
|
+
exclude torch_ext/ple_directstorage_hip.hip
|
|
13
15
|
recursive-include tests *.py
|
|
14
16
|
recursive-include codebooks *.bin
|
|
15
17
|
include torch_api.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hip-quant
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.4
|
|
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
|
|
@@ -256,6 +256,14 @@ Dynamic: license-file
|
|
|
256
256
|
> target; f16 WMMA operands are the accurate choice. **Validate accuracy and
|
|
257
257
|
> convergence on your own workload before training with any of these paths.**
|
|
258
258
|
|
|
259
|
+
## 🌟 What's New in 2.2.4
|
|
260
|
+
|
|
261
|
+
> **2.2.4.post215** is the same release rebuilt against PyTorch 2.15 (TheRock / ROCm 7.14).
|
|
262
|
+
|
|
263
|
+
- **🛡️ Safer imatrix handling.** The Python quantization entry points validate full-matrix and llama-style per-column imatrices before native calls. The three GGML I-Quants that require importance data warn once when the native unweighted fallback is used.
|
|
264
|
+
- **🧵 Thread-safe HIP initialization.** Quantization selects the cached HIP device on each calling thread and serializes device/codebook initialization, avoiding worker-thread launches against an unintended device.
|
|
265
|
+
- **📦 Native PLE reads on Windows.** The optional IOCP reader fills caller-owned pinned memory for large row batches. The DirectStorage backend is not included in this release.
|
|
266
|
+
|
|
259
267
|
## 🌟 What's New in 2.2.3
|
|
260
268
|
|
|
261
269
|
> **2.2.3.post215** is the same release rebuilt against PyTorch 2.15 (TheRock / ROCm 7.14).
|
|
@@ -283,7 +291,7 @@ Security, correctness and robustness fixes from an internal audit:
|
|
|
283
291
|
|
|
284
292
|
- **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.
|
|
285
293
|
- **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.
|
|
286
|
-
- **Offline API**:
|
|
294
|
+
- **Offline API**: quantize_from_fp8 validates the imatrix element count (was a host + device out-of-bounds read), ggml_blck_size_for restype corrected, math.prod for element counts.
|
|
287
295
|
- **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`.
|
|
288
296
|
- **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.
|
|
289
297
|
|
|
@@ -342,9 +350,11 @@ out = hip_quant.wave_attn(q, k, v) # native FP8 WMMA (inference-grade)
|
|
|
342
350
|
# Native FP16 WMMA training kernels on gfx1201 (forward + backward, no Triton):
|
|
343
351
|
qh, kh, vh = q.half(), k.half(), v.half()
|
|
344
352
|
out_fp16 = hip_quant.wave_attn(qh, kh, vh, precision="fp16")
|
|
345
|
-
# BF16
|
|
353
|
+
# Native BF16 WMMA training kernels on gfx1201:
|
|
346
354
|
qbf, kbf, vbf = q.bfloat16(), k.bfloat16(), v.bfloat16()
|
|
347
355
|
out_bf16 = hip_quant.wave_attn(qbf, kbf, vbf, precision="bf16")
|
|
356
|
+
# Deprecated Triton compatibility path:
|
|
357
|
+
out_bf16_triton = hip_quant.wave_attn(qbf, kbf, vbf, precision="bf16_triton")
|
|
348
358
|
# Or defer to PyTorch SDPA entirely:
|
|
349
359
|
out_precise = hip_quant.wave_attn(q, k, v, precision="sdpa")
|
|
350
360
|
```
|
|
@@ -382,27 +392,33 @@ See `benchmarks/wave_attn_train_results.md` for methods and all metrics.
|
|
|
382
392
|
> including for prequantized `uint8` inputs. The SDPA precision mode is for
|
|
383
393
|
> floating-point training inputs and returns a float32 output.
|
|
384
394
|
|
|
385
|
-
**BF16 training mode
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
at
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
395
|
+
**BF16 training mode:** `precision="bf16"` uses native GFX12 BF16 WMMA forward
|
|
396
|
+
and backward kernels. Q/K/V must share batch, head count, and head dimension;
|
|
397
|
+
K and V must have equal sequence lengths, while query and key lengths may differ.
|
|
398
|
+
The supported head dimensions are 64 and 128. The path returns BF16 output and
|
|
399
|
+
gradients, and saves FP32 output and softmax state for backward. Backward uses
|
|
400
|
+
the incoming BF16 gradient directly, avoiding an FP32 round trip and a duplicate
|
|
401
|
+
BF16 gradient buffer. The accuracy
|
|
402
|
+
and guard cases in `tests/torch/test_wave_attn_train_bf16.py` cover distinct
|
|
403
|
+
query/key lengths and invalid native-binding arguments. A bounded GPU graph
|
|
404
|
+
replay at `B=1,H=8,S=512,D=64` measured native BF16 at 0.98x native FP16 time
|
|
405
|
+
for noncausal and causal forward plus backward; this is a shape-specific
|
|
406
|
+
comparison, not a universal speed claim.
|
|
407
|
+
|
|
408
|
+
The previous BF16 performance table and 3,000-update checkpoint run below used
|
|
409
|
+
the Triton implementation. It is retained temporarily as
|
|
410
|
+
`precision="bf16_triton"`, which emits a `FutureWarning`; use `precision="bf16"`
|
|
411
|
+
for the native path. The Triton path requires ROCm Triton. See
|
|
412
|
+
`benchmarks/check_wave_attn_train_gate.py` and
|
|
413
|
+
`benchmarks/wave_attn_train_results.md` for the historical Triton measurements.
|
|
399
414
|
|
|
400
415
|
To route timm's SDPA calls through the BF16 path, set
|
|
401
416
|
`HIP_QUANT_WAVE_ATTN_PRECISION=bf16` before calling `patch_sdpa()` (or before a
|
|
402
417
|
trainer's `--wave-attention` flag). The helper makes timm's transposed Q/K/V
|
|
403
418
|
views contiguous and returns BF16 outputs; unsupported attention shapes still
|
|
404
419
|
use SDPA. A BF16 kernel error propagates instead of silently falling back.
|
|
405
|
-
From a real PlantUnified checkpoint at step 131,780, the
|
|
420
|
+
From a real PlantUnified checkpoint at step 131,780, the legacy
|
|
421
|
+
`precision="bf16_triton"` path completed
|
|
406
422
|
3,000 more training updates with finite loss and gradients, using 24 attention
|
|
407
423
|
calls per update across the 12 DINOv3 blocks and their checkpoint recomputations.
|
|
408
424
|
The bounded run did not perform EMA or validation; the eight-step matched A/B
|
|
@@ -510,13 +526,13 @@ Non-linear quants that preserve quality at extreme low bits:
|
|
|
510
526
|
- `IQ1_S`, `IQ1_M`, `IQ2_XXS`, `IQ2_XS`, `IQ2_S`, `IQ3_XXS`, `IQ3_S`, `IQ4_NL`, `IQ4_XS`
|
|
511
527
|
|
|
512
528
|
imatrix contract: llama.cpp defines **one float per input column, shared
|
|
513
|
-
across rows** (size `ne[0]`).
|
|
514
|
-
|
|
515
|
-
|
|
529
|
+
across rows** (size `ne[0]`). The Python APIs accept that `(n_per_row,)`
|
|
530
|
+
vector or a full matrix and tile vectors internally because the current
|
|
531
|
+
kernels index `imatrix + row*n_per_row`. Weighting math matches llama
|
|
516
532
|
(`qw[i] * sqrt(sigma2 + x[i]^2)`); all-ones imatrix is the identity and is
|
|
517
|
-
what the byte-exact tests use today.
|
|
518
|
-
|
|
519
|
-
|
|
533
|
+
what the byte-exact tests use today. The three llama-required I-Quants warn
|
|
534
|
+
once per process when called without an imatrix. `.dat` loading and
|
|
535
|
+
non-trivial-imatrix byte-exact coverage remain in `IMATRIX_PLAN.md`.
|
|
520
536
|
|
|
521
537
|
### ⚖️ Ternary Quants
|
|
522
538
|
For models trained to be ternary (BitNet, TriLM):
|
|
@@ -543,6 +559,27 @@ x = torch.randn(4096, 4096, device="cuda", dtype=torch.bfloat16)
|
|
|
543
559
|
q, s = hq.quantize_mxfp8_e4m3(x) # q:uint8 [4096,4096], s:uint8 UE8M0 [4096,128]
|
|
544
560
|
y = hq.dequantize_mxfp8_e4m3(q, s) # float32
|
|
545
561
|
q2, s2 = hq.quantize_mxfp8_e5m2(x) # E5M2 variant for gradients
|
|
562
|
+
|
|
563
|
+
# Direct OCP MXFP8 GEMM: no FP32 dequantization buffer.
|
|
564
|
+
w = torch.randn(4096, 4096, device="cuda", dtype=torch.bfloat16)
|
|
565
|
+
wq, ws = hq.quantize_mxfp8_e4m3(w)
|
|
566
|
+
y = hq.mxfp8_linear_forward_ue8m0(q, s, wq, ws, x)
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
The gfx12 path applies both UE8M0 scales to each K=32 dot-product partial
|
|
570
|
+
while the E4M3 operands stay packed for WMMA.
|
|
571
|
+
|
|
572
|
+
#### Experimental signed MXINT4 (custom format)
|
|
573
|
+
|
|
574
|
+
This is a hip_quant format, not an OCP v1.0 MX format: signed symmetric int4
|
|
575
|
+
values in `[-7,7]`, with one UE8M0 scale per 32 contiguous values. Quantized
|
|
576
|
+
operands stay nibble-packed and the GEMM uses RDNA4's native IU4 WMMA
|
|
577
|
+
instruction; software applies the block scales to each K=32 partial.
|
|
578
|
+
|
|
579
|
+
```python
|
|
580
|
+
a4, a4_scales = hq.quantize_mxint4(x)
|
|
581
|
+
w4, w4_scales = hq.quantize_mxint4(w)
|
|
582
|
+
y4 = hq.mxint4_wmma_linear(a4, a4_scales, w4, w4_scales, x)
|
|
546
583
|
```
|
|
547
584
|
|
|
548
585
|
CPU reference in `tests/test_mxfp8_numerical.py` (11 cases: `zero`, `1.0→ue119 q0x78`, `448→ue127`, `500→ue128`, `NaN/Inf`, `subnormal`) and GPU `tests/torch/test_mxfp8_torch.py` (10 warp-correct cases, `tail 33/31`, `F16/BF16`, `vs FP32-scale 1.4×`).
|
|
@@ -645,7 +682,7 @@ pip install hip-quant
|
|
|
645
682
|
pip install "hip-quant[torch]"
|
|
646
683
|
|
|
647
684
|
# Or a local wheel
|
|
648
|
-
pip install dist/hip_quant-2.2.
|
|
685
|
+
pip install dist/hip_quant-2.2.4-cp312-cp312-win_amd64.whl
|
|
649
686
|
```
|
|
650
687
|
|
|
651
688
|
Two wheels are published per release, one per PyTorch ABI. Install the one that
|
|
@@ -653,11 +690,11 @@ matches your PyTorch, so the extension loads without an ABI mismatch:
|
|
|
653
690
|
|
|
654
691
|
| Wheel | PyTorch | ROCm |
|
|
655
692
|
|---|---|---|
|
|
656
|
-
| `hip-quant==2.2.
|
|
657
|
-
| `hip-quant==2.2.
|
|
693
|
+
| `hip-quant==2.2.4` | 2.9.x | ROCm 7.2.1 |
|
|
694
|
+
| `hip-quant==2.2.4.post215` | 2.15 / TheRock | ROCm 7.14 |
|
|
658
695
|
|
|
659
696
|
```powershell
|
|
660
|
-
pip install "hip-quant==2.2.
|
|
697
|
+
pip install "hip-quant==2.2.4.post215" # PyTorch 2.15 / TheRock
|
|
661
698
|
```
|
|
662
699
|
|
|
663
700
|
#### Custom PyTorch 2.15 (self-hosted wheels)
|
|
@@ -667,7 +704,7 @@ Its wheels live in a public Backblaze B2 bucket; point pip at the index page
|
|
|
667
704
|
with `--find-links`:
|
|
668
705
|
|
|
669
706
|
```powershell
|
|
670
|
-
pip install "hip-quant==2.2.
|
|
707
|
+
pip install "hip-quant==2.2.4.post215" `
|
|
671
708
|
--find-links https://dl.hipquant.download/file/Torchs/torch_index.html
|
|
672
709
|
```
|
|
673
710
|
|
|
@@ -1241,9 +1278,8 @@ All PyTorch extension functions are guarded against:
|
|
|
1241
1278
|
- **Gated-norm weight layout** — `fast_rms_norm_gated_forward` dispatches by
|
|
1242
1279
|
`w.numel()`: per-head `[H,D]` or shared `[D]` (stride 0). Anything else raises
|
|
1243
1280
|
instead of reading out of bounds (regression: Qwen3.5 shared `ssm_norm`)
|
|
1244
|
-
- **imatrix shape** —
|
|
1245
|
-
|
|
1246
|
-
does not validate yet — pass a full matrix there (see `IMATRIX_PLAN.md`)
|
|
1281
|
+
- **imatrix shape** — all Python quantization entry points accept only a
|
|
1282
|
+
matching full matrix or a per-column vector and validate before native calls.
|
|
1247
1283
|
|
|
1248
1284
|
---
|
|
1249
1285
|
|
|
@@ -31,6 +31,14 @@
|
|
|
31
31
|
> target; f16 WMMA operands are the accurate choice. **Validate accuracy and
|
|
32
32
|
> convergence on your own workload before training with any of these paths.**
|
|
33
33
|
|
|
34
|
+
## 🌟 What's New in 2.2.4
|
|
35
|
+
|
|
36
|
+
> **2.2.4.post215** is the same release rebuilt against PyTorch 2.15 (TheRock / ROCm 7.14).
|
|
37
|
+
|
|
38
|
+
- **🛡️ Safer imatrix handling.** The Python quantization entry points validate full-matrix and llama-style per-column imatrices before native calls. The three GGML I-Quants that require importance data warn once when the native unweighted fallback is used.
|
|
39
|
+
- **🧵 Thread-safe HIP initialization.** Quantization selects the cached HIP device on each calling thread and serializes device/codebook initialization, avoiding worker-thread launches against an unintended device.
|
|
40
|
+
- **📦 Native PLE reads on Windows.** The optional IOCP reader fills caller-owned pinned memory for large row batches. The DirectStorage backend is not included in this release.
|
|
41
|
+
|
|
34
42
|
## 🌟 What's New in 2.2.3
|
|
35
43
|
|
|
36
44
|
> **2.2.3.post215** is the same release rebuilt against PyTorch 2.15 (TheRock / ROCm 7.14).
|
|
@@ -58,7 +66,7 @@ Security, correctness and robustness fixes from an internal audit:
|
|
|
58
66
|
|
|
59
67
|
- **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.
|
|
60
68
|
- **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.
|
|
61
|
-
- **Offline API**:
|
|
69
|
+
- **Offline API**: quantize_from_fp8 validates the imatrix element count (was a host + device out-of-bounds read), ggml_blck_size_for restype corrected, math.prod for element counts.
|
|
62
70
|
- **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`.
|
|
63
71
|
- **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.
|
|
64
72
|
|
|
@@ -117,9 +125,11 @@ out = hip_quant.wave_attn(q, k, v) # native FP8 WMMA (inference-grade)
|
|
|
117
125
|
# Native FP16 WMMA training kernels on gfx1201 (forward + backward, no Triton):
|
|
118
126
|
qh, kh, vh = q.half(), k.half(), v.half()
|
|
119
127
|
out_fp16 = hip_quant.wave_attn(qh, kh, vh, precision="fp16")
|
|
120
|
-
# BF16
|
|
128
|
+
# Native BF16 WMMA training kernels on gfx1201:
|
|
121
129
|
qbf, kbf, vbf = q.bfloat16(), k.bfloat16(), v.bfloat16()
|
|
122
130
|
out_bf16 = hip_quant.wave_attn(qbf, kbf, vbf, precision="bf16")
|
|
131
|
+
# Deprecated Triton compatibility path:
|
|
132
|
+
out_bf16_triton = hip_quant.wave_attn(qbf, kbf, vbf, precision="bf16_triton")
|
|
123
133
|
# Or defer to PyTorch SDPA entirely:
|
|
124
134
|
out_precise = hip_quant.wave_attn(q, k, v, precision="sdpa")
|
|
125
135
|
```
|
|
@@ -157,27 +167,33 @@ See `benchmarks/wave_attn_train_results.md` for methods and all metrics.
|
|
|
157
167
|
> including for prequantized `uint8` inputs. The SDPA precision mode is for
|
|
158
168
|
> floating-point training inputs and returns a float32 output.
|
|
159
169
|
|
|
160
|
-
**BF16 training mode
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
at
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
170
|
+
**BF16 training mode:** `precision="bf16"` uses native GFX12 BF16 WMMA forward
|
|
171
|
+
and backward kernels. Q/K/V must share batch, head count, and head dimension;
|
|
172
|
+
K and V must have equal sequence lengths, while query and key lengths may differ.
|
|
173
|
+
The supported head dimensions are 64 and 128. The path returns BF16 output and
|
|
174
|
+
gradients, and saves FP32 output and softmax state for backward. Backward uses
|
|
175
|
+
the incoming BF16 gradient directly, avoiding an FP32 round trip and a duplicate
|
|
176
|
+
BF16 gradient buffer. The accuracy
|
|
177
|
+
and guard cases in `tests/torch/test_wave_attn_train_bf16.py` cover distinct
|
|
178
|
+
query/key lengths and invalid native-binding arguments. A bounded GPU graph
|
|
179
|
+
replay at `B=1,H=8,S=512,D=64` measured native BF16 at 0.98x native FP16 time
|
|
180
|
+
for noncausal and causal forward plus backward; this is a shape-specific
|
|
181
|
+
comparison, not a universal speed claim.
|
|
182
|
+
|
|
183
|
+
The previous BF16 performance table and 3,000-update checkpoint run below used
|
|
184
|
+
the Triton implementation. It is retained temporarily as
|
|
185
|
+
`precision="bf16_triton"`, which emits a `FutureWarning`; use `precision="bf16"`
|
|
186
|
+
for the native path. The Triton path requires ROCm Triton. See
|
|
187
|
+
`benchmarks/check_wave_attn_train_gate.py` and
|
|
188
|
+
`benchmarks/wave_attn_train_results.md` for the historical Triton measurements.
|
|
174
189
|
|
|
175
190
|
To route timm's SDPA calls through the BF16 path, set
|
|
176
191
|
`HIP_QUANT_WAVE_ATTN_PRECISION=bf16` before calling `patch_sdpa()` (or before a
|
|
177
192
|
trainer's `--wave-attention` flag). The helper makes timm's transposed Q/K/V
|
|
178
193
|
views contiguous and returns BF16 outputs; unsupported attention shapes still
|
|
179
194
|
use SDPA. A BF16 kernel error propagates instead of silently falling back.
|
|
180
|
-
From a real PlantUnified checkpoint at step 131,780, the
|
|
195
|
+
From a real PlantUnified checkpoint at step 131,780, the legacy
|
|
196
|
+
`precision="bf16_triton"` path completed
|
|
181
197
|
3,000 more training updates with finite loss and gradients, using 24 attention
|
|
182
198
|
calls per update across the 12 DINOv3 blocks and their checkpoint recomputations.
|
|
183
199
|
The bounded run did not perform EMA or validation; the eight-step matched A/B
|
|
@@ -285,13 +301,13 @@ Non-linear quants that preserve quality at extreme low bits:
|
|
|
285
301
|
- `IQ1_S`, `IQ1_M`, `IQ2_XXS`, `IQ2_XS`, `IQ2_S`, `IQ3_XXS`, `IQ3_S`, `IQ4_NL`, `IQ4_XS`
|
|
286
302
|
|
|
287
303
|
imatrix contract: llama.cpp defines **one float per input column, shared
|
|
288
|
-
across rows** (size `ne[0]`).
|
|
289
|
-
|
|
290
|
-
|
|
304
|
+
across rows** (size `ne[0]`). The Python APIs accept that `(n_per_row,)`
|
|
305
|
+
vector or a full matrix and tile vectors internally because the current
|
|
306
|
+
kernels index `imatrix + row*n_per_row`. Weighting math matches llama
|
|
291
307
|
(`qw[i] * sqrt(sigma2 + x[i]^2)`); all-ones imatrix is the identity and is
|
|
292
|
-
what the byte-exact tests use today.
|
|
293
|
-
|
|
294
|
-
|
|
308
|
+
what the byte-exact tests use today. The three llama-required I-Quants warn
|
|
309
|
+
once per process when called without an imatrix. `.dat` loading and
|
|
310
|
+
non-trivial-imatrix byte-exact coverage remain in `IMATRIX_PLAN.md`.
|
|
295
311
|
|
|
296
312
|
### ⚖️ Ternary Quants
|
|
297
313
|
For models trained to be ternary (BitNet, TriLM):
|
|
@@ -318,6 +334,27 @@ x = torch.randn(4096, 4096, device="cuda", dtype=torch.bfloat16)
|
|
|
318
334
|
q, s = hq.quantize_mxfp8_e4m3(x) # q:uint8 [4096,4096], s:uint8 UE8M0 [4096,128]
|
|
319
335
|
y = hq.dequantize_mxfp8_e4m3(q, s) # float32
|
|
320
336
|
q2, s2 = hq.quantize_mxfp8_e5m2(x) # E5M2 variant for gradients
|
|
337
|
+
|
|
338
|
+
# Direct OCP MXFP8 GEMM: no FP32 dequantization buffer.
|
|
339
|
+
w = torch.randn(4096, 4096, device="cuda", dtype=torch.bfloat16)
|
|
340
|
+
wq, ws = hq.quantize_mxfp8_e4m3(w)
|
|
341
|
+
y = hq.mxfp8_linear_forward_ue8m0(q, s, wq, ws, x)
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
The gfx12 path applies both UE8M0 scales to each K=32 dot-product partial
|
|
345
|
+
while the E4M3 operands stay packed for WMMA.
|
|
346
|
+
|
|
347
|
+
#### Experimental signed MXINT4 (custom format)
|
|
348
|
+
|
|
349
|
+
This is a hip_quant format, not an OCP v1.0 MX format: signed symmetric int4
|
|
350
|
+
values in `[-7,7]`, with one UE8M0 scale per 32 contiguous values. Quantized
|
|
351
|
+
operands stay nibble-packed and the GEMM uses RDNA4's native IU4 WMMA
|
|
352
|
+
instruction; software applies the block scales to each K=32 partial.
|
|
353
|
+
|
|
354
|
+
```python
|
|
355
|
+
a4, a4_scales = hq.quantize_mxint4(x)
|
|
356
|
+
w4, w4_scales = hq.quantize_mxint4(w)
|
|
357
|
+
y4 = hq.mxint4_wmma_linear(a4, a4_scales, w4, w4_scales, x)
|
|
321
358
|
```
|
|
322
359
|
|
|
323
360
|
CPU reference in `tests/test_mxfp8_numerical.py` (11 cases: `zero`, `1.0→ue119 q0x78`, `448→ue127`, `500→ue128`, `NaN/Inf`, `subnormal`) and GPU `tests/torch/test_mxfp8_torch.py` (10 warp-correct cases, `tail 33/31`, `F16/BF16`, `vs FP32-scale 1.4×`).
|
|
@@ -420,7 +457,7 @@ pip install hip-quant
|
|
|
420
457
|
pip install "hip-quant[torch]"
|
|
421
458
|
|
|
422
459
|
# Or a local wheel
|
|
423
|
-
pip install dist/hip_quant-2.2.
|
|
460
|
+
pip install dist/hip_quant-2.2.4-cp312-cp312-win_amd64.whl
|
|
424
461
|
```
|
|
425
462
|
|
|
426
463
|
Two wheels are published per release, one per PyTorch ABI. Install the one that
|
|
@@ -428,11 +465,11 @@ matches your PyTorch, so the extension loads without an ABI mismatch:
|
|
|
428
465
|
|
|
429
466
|
| Wheel | PyTorch | ROCm |
|
|
430
467
|
|---|---|---|
|
|
431
|
-
| `hip-quant==2.2.
|
|
432
|
-
| `hip-quant==2.2.
|
|
468
|
+
| `hip-quant==2.2.4` | 2.9.x | ROCm 7.2.1 |
|
|
469
|
+
| `hip-quant==2.2.4.post215` | 2.15 / TheRock | ROCm 7.14 |
|
|
433
470
|
|
|
434
471
|
```powershell
|
|
435
|
-
pip install "hip-quant==2.2.
|
|
472
|
+
pip install "hip-quant==2.2.4.post215" # PyTorch 2.15 / TheRock
|
|
436
473
|
```
|
|
437
474
|
|
|
438
475
|
#### Custom PyTorch 2.15 (self-hosted wheels)
|
|
@@ -442,7 +479,7 @@ Its wheels live in a public Backblaze B2 bucket; point pip at the index page
|
|
|
442
479
|
with `--find-links`:
|
|
443
480
|
|
|
444
481
|
```powershell
|
|
445
|
-
pip install "hip-quant==2.2.
|
|
482
|
+
pip install "hip-quant==2.2.4.post215" `
|
|
446
483
|
--find-links https://dl.hipquant.download/file/Torchs/torch_index.html
|
|
447
484
|
```
|
|
448
485
|
|
|
@@ -1016,9 +1053,8 @@ All PyTorch extension functions are guarded against:
|
|
|
1016
1053
|
- **Gated-norm weight layout** — `fast_rms_norm_gated_forward` dispatches by
|
|
1017
1054
|
`w.numel()`: per-head `[H,D]` or shared `[D]` (stride 0). Anything else raises
|
|
1018
1055
|
instead of reading out of bounds (regression: Qwen3.5 shared `ssm_norm`)
|
|
1019
|
-
- **imatrix shape** —
|
|
1020
|
-
|
|
1021
|
-
does not validate yet — pass a full matrix there (see `IMATRIX_PLAN.md`)
|
|
1056
|
+
- **imatrix shape** — all Python quantization entry points accept only a
|
|
1057
|
+
matching full matrix or a per-column vector and validate before native calls.
|
|
1022
1058
|
|
|
1023
1059
|
---
|
|
1024
1060
|
|
|
@@ -2,8 +2,9 @@ import ctypes
|
|
|
2
2
|
import numpy as np
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
|
+
import warnings
|
|
5
6
|
|
|
6
|
-
__version__ = "2.2.
|
|
7
|
+
__version__ = "2.2.4"
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
_TORCH_EXPORTS = {
|
|
@@ -46,6 +47,14 @@ _TORCH_EXPORTS = {
|
|
|
46
47
|
"dequantize_e5m2",
|
|
47
48
|
"dequantize_e4m3_blockwise",
|
|
48
49
|
"dequantize_e5m2_blockwise",
|
|
50
|
+
"quantize_mxfp8_e4m3",
|
|
51
|
+
"quantize_mxfp8_e5m2",
|
|
52
|
+
"dequantize_mxfp8_e4m3",
|
|
53
|
+
"dequantize_mxfp8_e5m2",
|
|
54
|
+
"mxfp8_linear_forward_ue8m0",
|
|
55
|
+
"quantize_mxint4",
|
|
56
|
+
"mxint4_wmma_linear",
|
|
57
|
+
"MXINT4_BLOCK_SIZE",
|
|
49
58
|
# ── Attention ──────────────────────────────────────────
|
|
50
59
|
"wave_attn",
|
|
51
60
|
# ── Linear / GEMM ─────────────────────────────────────
|
|
@@ -54,6 +63,7 @@ _TORCH_EXPORTS = {
|
|
|
54
63
|
"fp8_linear_forward_fp8_weight",
|
|
55
64
|
"fp8_linear_forward_fp8_input",
|
|
56
65
|
"fp8_linear_forward_fp8_input_weight",
|
|
66
|
+
"fp8_grouped_expert_linear_forward_fp8_input_weight",
|
|
57
67
|
"pack_fp8_weight_for_wmma",
|
|
58
68
|
"fp8_linear_forward_fp8_input_weight_packed",
|
|
59
69
|
"fp8_linear_forward_blockwise",
|
|
@@ -160,6 +170,46 @@ GGML_TYPE = {
|
|
|
160
170
|
"F8_E5M2": 37,
|
|
161
171
|
}
|
|
162
172
|
|
|
173
|
+
_IMATRIX_REQUIRED_TYPES = frozenset(
|
|
174
|
+
(GGML_TYPE["IQ2_XXS"], GGML_TYPE["IQ2_XS"], GGML_TYPE["IQ1_S"])
|
|
175
|
+
)
|
|
176
|
+
_MISSING_IMATRIX_WARNED = False
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _as_nonempty_2d(array, dtype, name):
|
|
180
|
+
array = np.ascontiguousarray(array, dtype=dtype)
|
|
181
|
+
if array.ndim == 1:
|
|
182
|
+
array = array.reshape(1, -1)
|
|
183
|
+
if array.ndim != 2:
|
|
184
|
+
raise ValueError(f"{name} must be a 1-D or 2-D array")
|
|
185
|
+
if array.shape[0] == 0 or array.shape[1] == 0:
|
|
186
|
+
raise ValueError(f"{name} must contain at least one row and one element per row")
|
|
187
|
+
return array
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _prepare_imatrix(imatrix, shape, type_num):
|
|
191
|
+
global _MISSING_IMATRIX_WARNED
|
|
192
|
+
if imatrix is None:
|
|
193
|
+
if int(type_num) in _IMATRIX_REQUIRED_TYPES and not _MISSING_IMATRIX_WARNED:
|
|
194
|
+
warnings.warn(
|
|
195
|
+
"IQ2_XXS, IQ2_XS, and IQ1_S require an imatrix for GGML-compatible "
|
|
196
|
+
"quantization; using the native unweighted fallback",
|
|
197
|
+
UserWarning,
|
|
198
|
+
stacklevel=3,
|
|
199
|
+
)
|
|
200
|
+
_MISSING_IMATRIX_WARNED = True
|
|
201
|
+
return None
|
|
202
|
+
|
|
203
|
+
imatrix = np.asarray(imatrix, dtype=np.float32)
|
|
204
|
+
if imatrix.shape == (shape[1],):
|
|
205
|
+
# llama.cpp stores one weight per input column, shared by every row.
|
|
206
|
+
imatrix = np.broadcast_to(imatrix, shape)
|
|
207
|
+
elif imatrix.shape != shape:
|
|
208
|
+
raise ValueError(
|
|
209
|
+
f"imatrix shape {imatrix.shape} must be ({shape[1]},) or {shape}"
|
|
210
|
+
)
|
|
211
|
+
return np.ascontiguousarray(imatrix, dtype=np.float32)
|
|
212
|
+
|
|
163
213
|
GGML_TYPE_BLOCK_SIZE = {
|
|
164
214
|
2: 32,
|
|
165
215
|
3: 32,
|
|
@@ -527,9 +577,7 @@ class HipQuant:
|
|
|
527
577
|
"""
|
|
528
578
|
if self._quantize_stochastic_e5m2 is None:
|
|
529
579
|
raise RuntimeError("Stochastic E5M2 not available in loaded DLL")
|
|
530
|
-
arr =
|
|
531
|
-
if arr.ndim == 1:
|
|
532
|
-
arr = arr.reshape(1, -1)
|
|
580
|
+
arr = _as_nonempty_2d(arr, np.float32, "arr")
|
|
533
581
|
nrows, n_per_row = arr.shape
|
|
534
582
|
dst = np.empty(nrows * n_per_row, dtype=np.uint8)
|
|
535
583
|
result = self._quantize_stochastic_e5m2(
|
|
@@ -657,7 +705,7 @@ class HipQuant:
|
|
|
657
705
|
Args:
|
|
658
706
|
arr: 2-D float32 numpy array (nrows, n_per_row) or 1-D.
|
|
659
707
|
type_num: GGML type number (use GGML_TYPE dict).
|
|
660
|
-
imatrix: Optional
|
|
708
|
+
imatrix: Optional full matrix or llama-style per-column vector.
|
|
661
709
|
hq2_iterations: Lloyd iterations for HQ2 (1-16; default 4).
|
|
662
710
|
aq2_iterations: Lloyd iterations for AQ2 (1-16; default 8).
|
|
663
711
|
AQ2 should normally use an attention-derived imatrix.
|
|
@@ -665,9 +713,7 @@ class HipQuant:
|
|
|
665
713
|
Returns:
|
|
666
714
|
np.uint8 array of quantized bytes.
|
|
667
715
|
"""
|
|
668
|
-
arr =
|
|
669
|
-
if arr.ndim == 1:
|
|
670
|
-
arr = arr.reshape(1, -1)
|
|
716
|
+
arr = _as_nonempty_2d(arr, np.float32, "arr")
|
|
671
717
|
nrows, n_per_row = arr.shape
|
|
672
718
|
blck = self.blck_size(type_num)
|
|
673
719
|
if blck <= 0:
|
|
@@ -680,12 +726,11 @@ class HipQuant:
|
|
|
680
726
|
dst = np.empty(out_nbytes, dtype=np.uint8)
|
|
681
727
|
src_ptr = arr.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
682
728
|
dst_ptr = dst.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
imatrix
|
|
686
|
-
if imatrix
|
|
687
|
-
|
|
688
|
-
im_ptr = imatrix.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
729
|
+
imatrix = _prepare_imatrix(imatrix, arr.shape, type_num)
|
|
730
|
+
im_ptr = (
|
|
731
|
+
imatrix.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
732
|
+
if imatrix is not None else None
|
|
733
|
+
)
|
|
689
734
|
if int(type_num) in {GGML_TYPE["AQ2"], GGML_TYPE["AQ2_QK"], GGML_TYPE["AQ2_VO"]}:
|
|
690
735
|
if not 1 <= int(aq2_iterations) <= 16:
|
|
691
736
|
raise ValueError("aq2_iterations must be in [1, 16]")
|
|
@@ -729,11 +774,7 @@ class HipQuant:
|
|
|
729
774
|
raise RuntimeError(
|
|
730
775
|
"Loaded hip_quantize library does not support kernel benchmarking; rebuild it"
|
|
731
776
|
)
|
|
732
|
-
arr =
|
|
733
|
-
if arr.ndim == 1:
|
|
734
|
-
arr = arr.reshape(1, -1)
|
|
735
|
-
if arr.ndim != 2:
|
|
736
|
-
raise ValueError("arr must be a 1-D or 2-D float32 array")
|
|
777
|
+
arr = _as_nonempty_2d(arr, np.float32, "arr")
|
|
737
778
|
nrows, n_per_row = arr.shape
|
|
738
779
|
block_size = self.blck_size(type_num)
|
|
739
780
|
if block_size <= 0:
|
|
@@ -764,10 +805,12 @@ class HipQuant:
|
|
|
764
805
|
|
|
765
806
|
def quantize_numpy_to(self, arr, type_num, dst, imatrix=None, hq2_iterations=4,
|
|
766
807
|
aq2_iterations=8):
|
|
767
|
-
"""Quantize into a pre-allocated uint8 buffer. Modifies dst in-place.
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
808
|
+
"""Quantize into a pre-allocated uint8 buffer. Modifies dst in-place.
|
|
809
|
+
|
|
810
|
+
imatrix may be a full matrix matching arr or a per-column vector
|
|
811
|
+
shared by every row, as used by llama.cpp.
|
|
812
|
+
"""
|
|
813
|
+
arr = _as_nonempty_2d(arr, np.float32, "arr")
|
|
771
814
|
nrows, n_per_row = arr.shape
|
|
772
815
|
block_size = self.blck_size(type_num)
|
|
773
816
|
if block_size <= 0:
|
|
@@ -787,12 +830,11 @@ class HipQuant:
|
|
|
787
830
|
)
|
|
788
831
|
src_ptr = arr.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
789
832
|
dst_ptr = dst.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
imatrix
|
|
793
|
-
if imatrix
|
|
794
|
-
|
|
795
|
-
im_ptr = imatrix.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
833
|
+
imatrix = _prepare_imatrix(imatrix, arr.shape, type_num)
|
|
834
|
+
im_ptr = (
|
|
835
|
+
imatrix.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
836
|
+
if imatrix is not None else None
|
|
837
|
+
)
|
|
796
838
|
if int(type_num) in {GGML_TYPE["AQ2"], GGML_TYPE["AQ2_QK"], GGML_TYPE["AQ2_VO"]}:
|
|
797
839
|
if not 1 <= int(aq2_iterations) <= 16:
|
|
798
840
|
raise ValueError("aq2_iterations must be in [1, 16]")
|
|
@@ -837,16 +879,14 @@ class HipQuant:
|
|
|
837
879
|
or the output of quantize_numpy(..., GGML_TYPE["F8_E4M3"])
|
|
838
880
|
/ quantize_numpy(..., GGML_TYPE["F8_E5M2"]).
|
|
839
881
|
type_num: GGML type number for the output format.
|
|
840
|
-
imatrix: Optional
|
|
882
|
+
imatrix: Optional full matrix or per-column vector shared by rows.
|
|
841
883
|
source_format: "E4M3"/GGML_TYPE["F8_E4M3"] or
|
|
842
884
|
"E5M2"/GGML_TYPE["F8_E5M2"].
|
|
843
885
|
|
|
844
886
|
Returns:
|
|
845
887
|
np.uint8 array of quantized bytes.
|
|
846
888
|
"""
|
|
847
|
-
arr_fp8 =
|
|
848
|
-
if arr_fp8.ndim == 1:
|
|
849
|
-
arr_fp8 = arr_fp8.reshape(1, -1)
|
|
889
|
+
arr_fp8 = _as_nonempty_2d(arr_fp8, np.uint8, "arr_fp8")
|
|
850
890
|
nrows, n_per_row = arr_fp8.shape
|
|
851
891
|
blck = self.blck_size(type_num)
|
|
852
892
|
if blck <= 0:
|
|
@@ -859,20 +899,11 @@ class HipQuant:
|
|
|
859
899
|
dst = np.empty(out_nbytes, dtype=np.uint8)
|
|
860
900
|
src_ptr = arr_fp8.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))
|
|
861
901
|
dst_ptr = dst.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8))
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
imatrix
|
|
865
|
-
|
|
866
|
-
|
|
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)
|
|
875
|
-
im_ptr = imatrix.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
902
|
+
imatrix = _prepare_imatrix(imatrix, arr_fp8.shape, type_num)
|
|
903
|
+
im_ptr = (
|
|
904
|
+
imatrix.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
|
|
905
|
+
if imatrix is not None else None
|
|
906
|
+
)
|
|
876
907
|
if isinstance(source_format, str):
|
|
877
908
|
source_format = source_format.upper()
|
|
878
909
|
if source_format in ("E4M3", "F8_E4M3", GGML_TYPE["F8_E4M3"]):
|