Skip to content

Fix INT8 quantization Triton kernel for HIP/ROCm#58

Closed
jnolck wants to merge 5 commits into
Comfy-Org:mainfrom
jnolck:fix-triton-hip-int8-rounding
Closed

Fix INT8 quantization Triton kernel for HIP/ROCm#58
jnolck wants to merge 5 commits into
Comfy-Org:mainfrom
jnolck:fix-triton-hip-int8-rounding

Conversation

@jnolck

@jnolck jnolck commented Jun 27, 2026

Copy link
Copy Markdown

Replace libdevice.rint() with manual sign-aware rounding since Triton 3.6.0 HIP backend lacks rint, math.round, and int clamp. All 33 INT8 tests pass on gfx1100 (RDNA 3 / RX 7900 XT).

⬢ [jnolck@toolbx tests]$ python -m pytest test_int8.py -v
========================================================== test session starts ==========================================================
platform linux -- Python 3.12.13, pytest-7.4.4, pluggy-1.6.0 -- /home/jnolck/Documents/src/ai/.venv/bin/python
cachedir: .pytest_cache
rootdir: /var/home/jnolck/Documents/src/ai/comfy-kitchen
configfile: pytest.ini
plugins: anyio-4.13.0, dash-4.2.0, hydra-core-1.3.3
collected 33 items                                                                                                                      

test_int8.py::test_cuda_int8_cublas_turing_n_alignment PASSED                                                                     [  3%]
test_int8.py::test_eager_int8_matmul_turing_n_alignment PASSED                                                                    [  6%]
test_int8.py::TestTensorWiseINT8Layout::test_weight_quantize_shape_dtype PASSED                                                   [  9%]
test_int8.py::TestTensorWiseINT8Layout::test_activation_quantize_shape_dtype PASSED                                               [ 12%]
test_int8.py::TestTensorWiseINT8Layout::test_weight_dequantize_dtype PASSED                                                       [ 15%]
test_int8.py::TestTensorWiseINT8Layout::test_weight_roundtrip_error PASSED                                                        [ 18%]
test_int8.py::TestTensorWiseINT8Layout::test_state_dict_tensors_keys PASSED                                                       [ 21%]
test_int8.py::TestTensorWiseINT8Layout::test_supports_fast_matmul PASSED                                                          [ 24%]
test_int8.py::TestTensorWiseINT8Layout::test_linear_dispatch PASSED                                                               [ 27%]
test_int8.py::TestTensorWiseINT8Layout::test_linear_dispatch_uses_activation_dtype PASSED                                         [ 30%]
test_int8.py::TestTensorWiseINT8Layout::test_mm_dispatch PASSED                                                                   [ 33%]
test_int8.py::TestTensorWiseINT8Layout::test_mm_dispatch_uses_activation_dtype PASSED                                             [ 36%]
test_int8.py::TestTensorWiseINT8Layout::test_addmm_dispatch PASSED                                                                [ 39%]
test_int8.py::TestTensorWiseINT8Layout::test_addmm_dispatch_uses_activation_dtype PASSED                                          [ 42%]
test_int8.py::TestTensorWiseINT8Layout::test_int8_linear_correctness[triton] PASSED                                               [ 45%]
test_int8.py::TestTensorWiseINT8Layout::test_int8_linear_correctness[eager] PASSED                                                [ 48%]
test_int8.py::TestTensorWiseINT8Layout::test_public_api_quantize_tensorwise PASSED                                                [ 51%]
test_int8.py::TestTensorWiseINT8Layout::test_public_api_quantize_rowwise PASSED                                                   [ 54%]
test_int8.py::TestTensorWiseINT8Layout::test_public_api_dequantize_simple PASSED                                                  [ 57%]
test_int8.py::TestTensorWiseINT8Layout::test_public_api_int8_linear PASSED                                                        [ 60%]
test_int8.py::TestTensorWiseINT8Layout::test_convrot_hadamard_properties PASSED                                                   [ 63%]
test_int8.py::TestTensorWiseINT8Layout::test_convrot_param_validation PASSED                                                      [ 66%]
test_int8.py::TestTensorWiseINT8Layout::test_convrot_weight_roundtrip PASSED                                                      [ 69%]
test_int8.py::TestTensorWiseINT8Layout::test_convrot_divisibility PASSED                                                          [ 72%]
test_int8.py::TestTensorWiseINT8Layout::test_convrot_linear_mm_addmm_dispatch PASSED                                              [ 75%]
test_int8.py::TestTensorWiseINT8Layout::test_convrot_triton_fused_correctness PASSED                                              [ 78%]
test_int8.py::TestTensorWisePublicAPI::test_public_api_quantize_tensorwise PASSED                                                 [ 81%]
test_int8.py::TestTensorWisePublicAPI::test_public_api_quantize_rowwise PASSED                                                    [ 84%]
test_int8.py::TestTensorWisePublicAPI::test_public_api_dequantize_simple PASSED                                                   [ 87%]
test_int8.py::TestTensorWisePublicAPI::test_public_api_int8_linear PASSED                                                         [ 90%]
test_int8.py::TestTensorWisePublicAPI::test_eager_int8_linear_single_row PASSED                                                   [ 93%]
test_int8.py::TestTensorWisePublicAPI::test_eager_int8_linear_pads_k_to_int8_mm_tile PASSED                                       [ 96%]
test_int8.py::TestTensorWisePublicAPI::test_eager_int8_linear_pads_n_to_int8_mm_tile PASSED                                       [100%]

========================================================== 33 passed in 13.94s ==========================================================

A lot of them were failing before and I was getting seg faults when trying to run workflows and started comfy with --enable-triton-backend.

@github-actions

Copy link
Copy Markdown

🎉 Thank you for your contribution, we really appreciate it! 🎉

Like many open source projects, we require contributors to sign our Contributor License Agreement (CLA). A CLA makes the ownership of contributions explicit, so contributors and the project share a clear understanding of how the code can be used. By signing, you:

  • Confirm that you own your contribution.
  • Keep the right to reuse your own code.
  • Grant us a copyright license to include and share it within our projects.

CLAs are standard practice across major open source projects including those under the Apache Software Foundation and the Linux Foundation. Ours is based on the Apache Software Foundation's CLA. Most importantly, it would enable us to relicense the project under a more permissive license in the future, giving the project and its community greater flexibility.

To sign, please post a new comment on this PR with exactly the following text:


I have read and agree to the Contributor License Agreement


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jnolck, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 38 minutes and 59 seconds. Learn how PR review limits work.

To continue reviewing without waiting, enable usage-based billing in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: efdb6f78-8d5b-4415-9d51-241c93cf889a

📥 Commits

Reviewing files that changed from the base of the PR and between f9161aa and 7ded4d8.

📒 Files selected for processing (1)
  • comfy_kitchen/backends/triton/quantization.py
📝 Walkthrough

Walkthrough

_quantize_rowwise_kernel now uses manual round-half-to-even logic for INT8 quantization before clamp/cast/store. No other functional changes are shown in the diff.

Changes

INT8 rounding change

Layer / File(s) Summary
INT8 rowwise rounding logic change
comfy_kitchen/backends/triton/quantization.py
_quantize_rowwise_kernel replaces libdevice.rint(q_f) with manual round-half-to-even handling, then clamps in float space, converts to int32, and stores as int8.
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jnolck

jnolck commented Jun 27, 2026

Copy link
Copy Markdown
Author

I have read and agree to the Contributor License Agreement.

Replace libdevice.rint() with manual sign-aware rounding since
Triton 3.6.0 HIP backend lacks rint, math.round, and int clamp.
All 33 INT8 tests pass on gfx1100 (RDNA 3 / RX 7900 XT).
@jnolck
jnolck force-pushed the fix-triton-hip-int8-rounding branch from 8cffa89 to fe31d4b Compare June 27, 2026 20:22

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@comfy_kitchen/backends/triton/quantization.py`:
- Around line 805-812: The rounding logic in the quantization path uses a
sign-based bias, which changes tie handling away from the previous nearest-even
behavior. Update the rounding in the relevant Triton quantization routine (the
block that computes rounding_bias and q_i) so exact .5 cases still round
ties-to-even like rint, or otherwise make the new rounding contract explicit and
add coverage for it. Verify the fix against the quantization conversion path
before the final int32 cast.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ed7287e6-6b0c-4147-a7bb-192efbac7fd2

📥 Commits

Reviewing files that changed from the base of the PR and between 8cffa89 and fe31d4b.

📒 Files selected for processing (1)
  • comfy_kitchen/backends/triton/quantization.py

Comment thread comfy_kitchen/backends/triton/quantization.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@comfy_kitchen/backends/triton/quantization.py`:
- Around line 803-817: The half-to-even tie handling in the quantization
rounding path is incorrect for negative .5 values because `floor_val % 2.0` in
the Triton/HIP path can be negative, so `q_i` in this rounding block
misclassifies odd negative floors. Update the parity check in the `tl.where`
logic to use a sign-safe even/odd test for `floor_val` so ties like -2.5 round
to the nearest even value, and add a test alongside this quantization code that
explicitly covers negative half-integers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d4016d49-1a8a-4806-b633-e5277d01f596

📥 Commits

Reviewing files that changed from the base of the PR and between fe31d4b and c86c859.

📒 Files selected for processing (1)
  • comfy_kitchen/backends/triton/quantization.py

Comment thread comfy_kitchen/backends/triton/quantization.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@comfy_kitchen/backends/triton/quantization.py`:
- Around line 813-815: The tie-breaking branch in _quantize_rowwise_kernel uses
is_odd before it is defined, so move or compute is_odd earlier in the kernel
before the frac == 0.5 path and ensure it is in scope when building q_i. Keep
the existing rounding logic intact, just make sure the local symbol is
initialized before the tl.where call that references floor_val + is_odd.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 63dd8e08-57d2-45be-a23d-a9705bc0fccc

📥 Commits

Reviewing files that changed from the base of the PR and between c86c859 and f9161aa.

📒 Files selected for processing (1)
  • comfy_kitchen/backends/triton/quantization.py

Comment thread comfy_kitchen/backends/triton/quantization.py
@patientx

patientx commented Jun 28, 2026

Copy link
Copy Markdown

gives black output specially on krea on most tries, same as my simpler version of this here #54 , custom node still has better performance

@jnolck

jnolck commented Jul 11, 2026

Copy link
Copy Markdown
Author

I noticed the change to 3.7 change to Triton.

@jnolck jnolck closed this Jul 11, 2026
@jnolck
jnolck deleted the fix-triton-hip-int8-rounding branch July 11, 2026 05:31
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 11, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants