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.
Files changed (212) hide show
  1. {hip_quant-2.2.3 → hip_quant-2.2.4}/MANIFEST.in +3 -1
  2. {hip_quant-2.2.3/hip_quant.egg-info → hip_quant-2.2.4}/PKG-INFO +68 -32
  3. {hip_quant-2.2.3 → hip_quant-2.2.4}/README.md +67 -31
  4. hip_quant-2.2.4/_C.cp312-win_amd64.pyd +4 -0
  5. {hip_quant-2.2.3 → hip_quant-2.2.4}/__init__.py +78 -47
  6. hip_quant-2.2.4/gguf.py +660 -0
  7. hip_quant-2.2.4/gguf_loader.py +687 -0
  8. {hip_quant-2.2.3 → hip_quant-2.2.4/hip_quant.egg-info}/PKG-INFO +68 -32
  9. {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/SOURCES.txt +24 -0
  10. {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quantize.cpp +11 -2
  11. hip_quant-2.2.4/hip_quantize_rocm721.dll +0 -0
  12. {hip_quant-2.2.3 → hip_quant-2.2.4}/pyproject.toml +10 -2
  13. {hip_quant-2.2.3 → hip_quant-2.2.4}/setup_torch.py +7 -0
  14. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_iquant_parallel.py +0 -3
  15. hip_quant-2.2.4/tests/test_ssm_heads_generic.py +92 -0
  16. hip_quant-2.2.4/tests/torch/test_wave_attn_train_bf16.py +281 -0
  17. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_api.py +1090 -49
  18. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/dequant_q_to_fp16.hip +19 -0
  19. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/fp8_linear_kernels_v2.hip +349 -0
  20. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/fp8_quant_kernels.hip +132 -0
  21. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/gemv_q_kernels.hip +202 -6
  22. hip_quant-2.2.4/torch_ext/hqnat_grouped_integer.hip +630 -0
  23. hip_quant-2.2.4/torch_ext/int3_g32_kernels.hip +663 -0
  24. hip_quant-2.2.4/torch_ext/int4_wmma_kernels.hip +417 -0
  25. hip_quant-2.2.4/torch_ext/int5_g32_kernels.hip +117 -0
  26. hip_quant-2.2.4/torch_ext/int6_g32_kernels.hip +118 -0
  27. hip_quant-2.2.4/torch_ext/lfm2_moe_int3_wmma.hip +281 -0
  28. hip_quant-2.2.4/torch_ext/ple_io.cpp +207 -0
  29. hip_quant-2.2.4/torch_ext/ple_io.h +49 -0
  30. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/pytorch_bindings.cpp +1396 -64
  31. hip_quant-2.2.4/torch_ext/qad_scale_gradient.hip +126 -0
  32. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/ssm_kernels.hip +53 -41
  33. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/ternary_gemv_kernels.hip +47 -63
  34. hip_quant-2.2.4/torch_ext/wave_attn_backward_bf16.hip +703 -0
  35. hip_quant-2.2.4/torch_ext/wave_attn_backward_mx.hip +680 -0
  36. hip_quant-2.2.4/torch_ext/wave_attn_bf16.hip +666 -0
  37. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wht_kernels.hip +123 -26
  38. {hip_quant-2.2.3 → hip_quant-2.2.4}/wave_attn_train_strided_triton.py +4 -4
  39. {hip_quant-2.2.3 → hip_quant-2.2.4}/wave_attn_train_triton.py +4 -4
  40. hip_quant-2.2.3/_C.cp312-win_amd64.pyd +0 -4
  41. hip_quant-2.2.3/gguf.py +0 -303
  42. hip_quant-2.2.3/gguf_loader.py +0 -112
  43. hip_quant-2.2.3/hip_quantize_rocm721.dll +0 -0
  44. hip_quant-2.2.3/tests/torch/test_wave_attn_train_bf16.py +0 -101
  45. hip_quant-2.2.3/torch_ext/int4_wmma_kernels.hip +0 -168
  46. {hip_quant-2.2.3 → hip_quant-2.2.4}/DOCUMENTATION.md +0 -0
  47. {hip_quant-2.2.3 → hip_quant-2.2.4}/LICENSE +0 -0
  48. {hip_quant-2.2.3 → hip_quant-2.2.4}/__main__.py +0 -0
  49. {hip_quant-2.2.3 → hip_quant-2.2.4}/bench_mxfp8.py +0 -0
  50. {hip_quant-2.2.3 → hip_quant-2.2.4}/bench_wave_attn_inference.py +0 -0
  51. {hip_quant-2.2.3 → hip_quant-2.2.4}/build.ps1 +0 -0
  52. {hip_quant-2.2.3 → hip_quant-2.2.4}/build.sh +0 -0
  53. {hip_quant-2.2.3 → hip_quant-2.2.4}/cdna_compat.py +0 -0
  54. {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq1_s.bin +0 -0
  55. {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq2_s.bin +0 -0
  56. {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq2_xs.bin +0 -0
  57. {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq2_xxs.bin +0 -0
  58. {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq3_s.bin +0 -0
  59. {hip_quant-2.2.3 → hip_quant-2.2.4}/codebooks/iq3_xxs.bin +0 -0
  60. {hip_quant-2.2.3 → hip_quant-2.2.4}/demo.py +0 -0
  61. {hip_quant-2.2.3 → hip_quant-2.2.4}/device_info.py +0 -0
  62. {hip_quant-2.2.3 → hip_quant-2.2.4}/diagnose_fp8_crash.py +0 -0
  63. {hip_quant-2.2.3 → hip_quant-2.2.4}/e2e_iq2s_iq1m.py +0 -0
  64. {hip_quant-2.2.3 → hip_quant-2.2.4}/get_hf_tensors.py +0 -0
  65. {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_iquant_util.h +0 -0
  66. {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/dependency_links.txt +0 -0
  67. {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/entry_points.txt +0 -0
  68. {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/not-zip-safe +0 -0
  69. {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/requires.txt +0 -0
  70. {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant.egg-info/top_level.txt +0 -0
  71. {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant_types.h +0 -0
  72. {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quant_util.h +0 -0
  73. {hip_quant-2.2.3 → hip_quant-2.2.4}/hip_quantize.dll +0 -0
  74. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/__init__.py +0 -0
  75. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/__main__.py +0 -0
  76. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/analyzer.py +0 -0
  77. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/api.py +0 -0
  78. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/archive.py +0 -0
  79. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/backends.py +0 -0
  80. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/format.py +0 -0
  81. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/hq3.py +0 -0
  82. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/hq8.py +0 -0
  83. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/mixed_policy.py +0 -0
  84. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/raw.py +0 -0
  85. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/safetensors_numpy.py +0 -0
  86. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/sensitivity.py +0 -0
  87. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/torch_inference.py +0 -0
  88. {hip_quant-2.2.3 → hip_quant-2.2.4}/hq2/transformers_loader.py +0 -0
  89. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/dequant_to_fp8.cu +0 -0
  90. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/direct_fp8_quant.cu +0 -0
  91. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/fp8_expand.cu +0 -0
  92. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/fp8_gemm_test.cu +0 -0
  93. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_aq2.cu +0 -0
  94. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_bf16.cu +0 -0
  95. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_f8_e4m3.cu +0 -0
  96. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_f8_e5m2.cu +0 -0
  97. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_hq2.cu +0 -0
  98. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq1_m.cu +0 -0
  99. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq1_s.cu +0 -0
  100. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq2_s.cu +0 -0
  101. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq2_xs.cu +0 -0
  102. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq2_xxs.cu +0 -0
  103. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq3_s.cu +0 -0
  104. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq3_xxs.cu +0 -0
  105. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq4_nl.cu +0 -0
  106. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_iq4_xs.cu +0 -0
  107. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q1_0.cu +0 -0
  108. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q2_0.cu +0 -0
  109. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q2_K.cu +0 -0
  110. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q3_K.cu +0 -0
  111. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q4_0.cu +0 -0
  112. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q4_1.cu +0 -0
  113. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q4_K.cu +0 -0
  114. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q5_0.cu +0 -0
  115. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q5_1.cu +0 -0
  116. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q5_K.cu +0 -0
  117. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q6_K.cu +0 -0
  118. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q8_0.cu +0 -0
  119. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q8_1.cu +0 -0
  120. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_q8_K.cu +0 -0
  121. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_tq1_0.cu +0 -0
  122. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/quant_tq2_0.cu +0 -0
  123. {hip_quant-2.2.3 → hip_quant-2.2.4}/kernels/wmma_diag.cu +0 -0
  124. {hip_quant-2.2.3 → hip_quant-2.2.4}/setup.cfg +0 -0
  125. {hip_quant-2.2.3 → hip_quant-2.2.4}/setup.py +0 -0
  126. {hip_quant-2.2.3 → hip_quant-2.2.4}/smi.py +0 -0
  127. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/__init__.py +0 -0
  128. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/bench_attn_compare.py +0 -0
  129. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/bench_iq2s_variants.py +0 -0
  130. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/bench_wave_prefill.py +0 -0
  131. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/debug_conv1d.py +0 -0
  132. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_aq2.py +0 -0
  133. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_bf16_numpy.py +0 -0
  134. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_compat.py +0 -0
  135. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_dequant_fp8.py +0 -0
  136. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_direct_fp8_quant.py +0 -0
  137. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_ffn_layer.py +0 -0
  138. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_fused_ssm_prefill.py +0 -0
  139. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_gemv_kquants.py +0 -0
  140. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_hq2.py +0 -0
  141. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_hq2_portable.py +0 -0
  142. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_hq8_g128.py +0 -0
  143. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_iq2s_iq1m_byte_exact.py +0 -0
  144. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_lazy_torch_import.py +0 -0
  145. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_mixed_policy.py +0 -0
  146. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_mixed_sensitivity.py +0 -0
  147. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_mxfp4_compat.py +0 -0
  148. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_mxfp4_native_contract.py +0 -0
  149. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_mxfp8_numerical.py +0 -0
  150. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_patch_hq_mixed_archive.py +0 -0
  151. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_pipeline.py +0 -0
  152. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_prefill_with_lse.py +0 -0
  153. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_q_to_fp8_gpu.py +0 -0
  154. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_qol.py +0 -0
  155. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_safetensors_numpy.py +0 -0
  156. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_v8.py +0 -0
  157. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_wave_attn_decode_hybrid.py +0 -0
  158. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_wave_prefill_gqa.py +0 -0
  159. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_wmma_diag.py +0 -0
  160. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/test_wmma_layout.py +0 -0
  161. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/bench_compare.py +0 -0
  162. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/bench_fp8.py +0 -0
  163. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/conftest.py +0 -0
  164. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_fp8.py +0 -0
  165. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_fp8_v2.py +0 -0
  166. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_hip_graph.py +0 -0
  167. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_mxfp4_native_contract_torch.py +0 -0
  168. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_mxfp4_to_fp8_torch.py +0 -0
  169. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_mxfp8_torch.py +0 -0
  170. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_q_to_fp8_torch.py +0 -0
  171. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_quant_transpose.py +0 -0
  172. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_wave_attn_backward_math.py +0 -0
  173. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_wave_attn_f16.py +0 -0
  174. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_wave_attn_f16_extreme.py +0 -0
  175. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/torch/test_wave_helpers_cpu.py +0 -0
  176. {hip_quant-2.2.3 → hip_quant-2.2.4}/tests/verify_fused_fp8_linear.py +0 -0
  177. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/.gpu-smi-version +0 -0
  178. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/fetch_gpu_smi.py +0 -0
  179. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/gpu-smi.exe +0 -0
  180. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/analyze.py +0 -0
  181. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/clean_wikitext.py +0 -0
  182. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/collect_hessians.py +0 -0
  183. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/hq2_bridge.py +0 -0
  184. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/hq2v.py +0 -0
  185. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/ldlq.py +0 -0
  186. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/ledger.py +0 -0
  187. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/run_ladder.py +0 -0
  188. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/safe_run.py +0 -0
  189. {hip_quant-2.2.3 → hip_quant-2.2.4}/tools/mlp_codec/validate_hessians.py +0 -0
  190. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/current_stream.hip +0 -0
  191. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/decode_quant_kernels.hip +0 -0
  192. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/fp8_linear_kernels.hip +0 -0
  193. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/hq2_linear_kernels.hip +0 -0
  194. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/hq3_linear_kernels.hip +0 -0
  195. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/hq8_g128_linear_kernels.hip +0 -0
  196. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/iq_grid_tables.h +0 -0
  197. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/kv_iu4_kernels.hip +0 -0
  198. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/mxfp4_to_fp8_kernels.hip +0 -0
  199. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/mxfp8_kernels.hip +0 -0
  200. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/pytorch_bindings_hip.cpp +0 -0
  201. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/q_to_fp8_kernels.hip +0 -0
  202. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/w4a16_gemv_kernels.hip +0 -0
  203. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn.hip +0 -0
  204. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_backward.hip +0 -0
  205. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_backward_f16.hip +0 -0
  206. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_common.h +0 -0
  207. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_decode.hip +0 -0
  208. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_diag.hip +0 -0
  209. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_f16.hip +0 -0
  210. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_long.hip +0 -0
  211. {hip_quant-2.2.3 → hip_quant-2.2.4}/torch_ext/wave_attn_prefill.hip +0 -0
  212. {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
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**: `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.
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 Triton fallback (requires ROCm Triton):
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 (experimental):** `precision="bf16"` uses Triton kernels
386
- that compile to gfx1201 `v_wmma_f32_16x16x16_bf16` instructions. It accepts
387
- contiguous, equal-shaped BF16 Q/K/V with head dimension 64 or 128; the output
388
- and input gradients are BF16. A separate FP32 output is saved for backward so
389
- large-score gradients retain accuracy. The full public forward/backward call
390
- beats default BF16 SDPA on the RX 9070 XT at `B=6,H=12,S=789`: 0.75 vs 1.02 ms
391
- for D=64 noncausal, 0.35 vs 0.98 ms causal; 2.24 vs 2.85 ms for D=128
392
- noncausal, 1.41 vs 1.96 ms causal (100 GPU-event repeats, medians of three
393
- rounds). Output and gradient relative L2 against FP32 MATH stay below 0.26%
394
- at input scales 1 and 5. Small attention calls can be slower than SDPA, so
395
- select this mode for measured training workloads. See
396
- `benchmarks/check_wave_attn_train_gate.py`,
397
- `benchmarks/check_plant_wave_continuation.py`, and
398
- `benchmarks/wave_attn_train_results.md` for the checks.
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 BF16 path completed
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]`). hip_quant kernels index `imatrix + row*n_per_row`,
514
- so `quantize_numpy` requires `imatrix.shape == arr.shape` — tile a raw llama
515
- `.dat` column vector across rows first. Weighting math matches llama
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. `quantize_from_fp8` does not yet validate
518
- imatrix shape (known gap — pass a full matrix). See `IMATRIX_PLAN.md` for the
519
- per-column-accept + non-trivial-imatrix test rollout.
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.3-cp312-cp312-win_amd64.whl
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.3` | 2.9.x | ROCm 7.2.1 |
657
- | `hip-quant==2.2.3.post215` | 2.15 / TheRock | ROCm 7.14 |
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.3.post215" # PyTorch 2.15 / TheRock
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.3.post215" `
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** — `quantize_numpy` requires `imatrix.shape == arr.shape`
1245
- (full matrix; tile llama per-column vectors first). `quantize_from_fp8`
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**: `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.
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 Triton fallback (requires ROCm Triton):
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 (experimental):** `precision="bf16"` uses Triton kernels
161
- that compile to gfx1201 `v_wmma_f32_16x16x16_bf16` instructions. It accepts
162
- contiguous, equal-shaped BF16 Q/K/V with head dimension 64 or 128; the output
163
- and input gradients are BF16. A separate FP32 output is saved for backward so
164
- large-score gradients retain accuracy. The full public forward/backward call
165
- beats default BF16 SDPA on the RX 9070 XT at `B=6,H=12,S=789`: 0.75 vs 1.02 ms
166
- for D=64 noncausal, 0.35 vs 0.98 ms causal; 2.24 vs 2.85 ms for D=128
167
- noncausal, 1.41 vs 1.96 ms causal (100 GPU-event repeats, medians of three
168
- rounds). Output and gradient relative L2 against FP32 MATH stay below 0.26%
169
- at input scales 1 and 5. Small attention calls can be slower than SDPA, so
170
- select this mode for measured training workloads. See
171
- `benchmarks/check_wave_attn_train_gate.py`,
172
- `benchmarks/check_plant_wave_continuation.py`, and
173
- `benchmarks/wave_attn_train_results.md` for the checks.
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 BF16 path completed
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]`). hip_quant kernels index `imatrix + row*n_per_row`,
289
- so `quantize_numpy` requires `imatrix.shape == arr.shape` — tile a raw llama
290
- `.dat` column vector across rows first. Weighting math matches llama
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. `quantize_from_fp8` does not yet validate
293
- imatrix shape (known gap — pass a full matrix). See `IMATRIX_PLAN.md` for the
294
- per-column-accept + non-trivial-imatrix test rollout.
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.3-cp312-cp312-win_amd64.whl
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.3` | 2.9.x | ROCm 7.2.1 |
432
- | `hip-quant==2.2.3.post215` | 2.15 / TheRock | ROCm 7.14 |
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.3.post215" # PyTorch 2.15 / TheRock
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.3.post215" `
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** — `quantize_numpy` requires `imatrix.shape == arr.shape`
1020
- (full matrix; tile llama per-column vectors first). `quantize_from_fp8`
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
 
@@ -0,0 +1,4 @@
1
+ [diffend] Oversized file quarantined before diffing.
2
+ name: hip_quant-2.2.4/_C.cp312-win_amd64.pyd
3
+ size: 48742400 bytes
4
+ sha256: 3cc14589a6ad04ba4981381c14660b79cc4104b851fffbef5fc0c512158e5be7
@@ -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.3"
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 = np.ascontiguousarray(arr, dtype=np.float32)
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 importance matrix (same shape as arr).
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 = np.ascontiguousarray(arr, dtype=np.float32)
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
- im_ptr = None
684
- if imatrix is not None:
685
- imatrix = np.ascontiguousarray(imatrix, dtype=np.float32)
686
- if imatrix.shape != arr.shape:
687
- raise ValueError(f"imatrix shape {imatrix.shape} != arr shape {arr.shape}")
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 = np.ascontiguousarray(arr, dtype=np.float32)
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
- arr = np.ascontiguousarray(arr, dtype=np.float32)
769
- if arr.ndim == 1:
770
- arr = arr.reshape(1, -1)
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
- im_ptr = None
791
- if imatrix is not None:
792
- imatrix = np.ascontiguousarray(imatrix, dtype=np.float32)
793
- if imatrix.shape != arr.shape:
794
- raise ValueError(f"imatrix shape {imatrix.shape} != arr shape {arr.shape}")
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 float32 importance matrix (same logical shape).
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 = np.ascontiguousarray(arr_fp8, dtype=np.uint8)
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
- im_ptr = None
863
- if imatrix is not None:
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)
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"]):