mirror of
https://github.com/Comfy-Org/comfy-kitchen.git
synced 2026-11-04 23:37:42 +00:00
[PR #264] Compile for sm_86 and keep its native int<->float conversions #270
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/comfy-kitchen#270
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/comfy-kitchen/pull/264
Author: @Many0therFunctions
Created: 10/20/2026
Status: 🔄 Open
Base:
main← Head:sm86-native-conversions📝 Commits (1)
86dfb29Compile for sm_86 and keep its native int<->float conversions📊 Changes
3 files changed (+13 additions, -9 deletions)
View changed files
📝
comfy_kitchen/backends/cuda/sage_attention/math.cuh(+5 -3)📝
comfy_kitchen/backends/cuda/sage_attention/mma.cuh(+6 -4)📝
setup.py(+2 -2)📄 Description
What
Two changes for GA10x cards (RTX 3060-3090, A6000, A40):
setup.py: add86-realto both default arch lists. The wheels have never carried sm_86 SASS; an sm_86 card runs the sm_80 cubin, which compiles int<->float conversions toI2F/F2Ion the XU pipe. The sm_86 cubin usesI2FP/F2IPinstead, which Nsight Compute places on the ALU pipe (one value perI2FP;F2IProunds, saturates and packs two values per instruction), with the XU instruction count unchanged, as on sm_89.sage_attention/math.cuh,mma.cuh: the arithmetic conversion forms from #234 / #235 (i2f_exact,pack_u8x4_exact,pack_u8x4_exact_nonneg) are gated__CUDA_ARCH__ < 860instead of< 890. They were measured on the sm_80 cubin (my #235 numbers say so: "A6000, sm_80 cubin from the default arch manifest"); on native sm_86 code they lose to the plain conversions everywhere.Nothing changes for sm_75 / sm_80 (still the arithmetic forms) or sm_89+ (still plain).
Why
Throughput of the conversion forms on an RTX A6000, elements per SM per clock (a 6-form microbenchmark, same source built
-arch=sm_80and-arch=sm_86, both run on the same card; source below):__int2float_rn(I2F / I2FP)x + 0x4B400000then- 1.5*2^23cvt.rni+cvt.pack.sat(F2I+I2IP / F2IP)+2^23+ 3 PRMTfminf 255++2^23+ 3 PRMT (current_nonneg)Nsight Compute on the same microbenchmark: on the sm_80 cubin the plain int->float adds one XU instruction per element; on the sm_86 cubin it adds one ALU instruction per element and no XU instructions. The arithmetic form adds one ALU (
IADD3) and one FMA (FADD) per element on both.Static SASS of the D128 128-row unmasked
qk_int_sv_i8_attn_kernel(sm_86): v0.2.39 4144 instructions, this PR 3232 (-22%); the 128-row key-mask kernel 18544 -> 13072. No spills at D128; register counts within 2 of v0.2.39. Profiled at B1 H56 S53730 D128, the kernel executes 65.9 G warp instructions instead of 88.6 G, in 710 M cycles instead of 731 M, with the XU instruction count identical (5.22 G: theex2andrcponly) and the ALU pipe at 19% (v0.2.39: 24%).Results
A6000 (sm_86, 300 W cap), both builds
86-real, sustained runs (1-3 s per arm, 3 rounds), interleaved A/B/B/A in separate processes, NVML-sampled,ck.int8_attentionbf16 in / bf16 out, D128:Note on the 128-row row: this PR needs 1.4% fewer cycles there but runs at a lower clock on this power-capped card. ncu shows the leaner kernel's L2 hit rate dropping from 98% to 60-80% (the co-resident CTAs stream the same K/V and only share it in L2 while they stay in step), so DRAM traffic rises from 2% to 26-30% of peak and the limiter takes the difference out of the clock. That is specific to a 300 W card; a 3080/3090 with more power headroom should see the cycle saving as time.
Output is bit-identical to v0.2.39 (and to the pre-#234 kernel) on D64 / D128 / D256, a partial tile and both masked paths.
tests/test_int8_attention.pyandtests/test_sol_attn.pypass on the sm_86 build (the twolong_sequence_and_partial_tile[scale<=0]cases fail as before: torch's reference returns NaN there).Without
86-realthe gate change is inert for wheel users, who all run the sm_80 cubin; with it, the current kernels alone gain 2.4% at 53k tokens unmasked (sm_86 cubin vs sm_80 cubin of v0.2.39, same source). An sm_86 cubin adds about 4 MB to the Linux wheel.Checking on a 3080 / 3090
Any GA10x card shows the same split: build once with
COMFY_CUDA_ARCHS="80-real"and once with"86-real",cuobjdump -sassthe two_C.abi3.soand grep the attention kernel forI2FvsI2FP; then time any int8 attention shape under 40k keys on both builds of this branch.conv_throughput.cu (the microbenchmark;
nvcc -O3 -arch=sm_86 conv_throughput.cu -o conv86 && ./conv86, likewise sm_80)🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.