Skip to content

Commit 04ac357

Browse files
committed
fix(triton): improve RDNA INT8 autotune selection
Keep ten candidates per device while replacing an unused gfx12-oriented tile with a small-M configuration on gfx11. Retain the original gfx12 pool, preserve useful BK128 candidates, and prune only the unstable 128x128x128 tile for small M. Keep device_index in the autotune key but mark it non-specializing in the generated kernels, so heterogeneous devices tune independently without duplicate code variants. Signed-off-by: liminfei-amd <91481003+liminfei-amd@users.noreply.github.com>
1 parent a6dcb22 commit 04ac357

2 files changed

Lines changed: 78 additions & 31 deletions

File tree

comfy_kitchen/backends/triton/quantization.py

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,7 @@ def triton_quantize_and_rotate_rowwise(x: torch.Tensor, h: torch.Tensor, group_s
857857

858858

859859
def _int8_autotune_configs():
860-
"""Return the default and RDNA-tuned INT8 matmul config pools."""
860+
"""Return the default and generation-specific RDNA config pools."""
861861
default_configs = [
862862
triton.Config({'block_m': 128, 'block_n': 256, 'block_k': 64, 'group_size_m': 8}, num_stages=3, num_warps=8),
863863
triton.Config({'block_m': 64, 'block_n': 256, 'block_k': 32, 'group_size_m': 8}, num_stages=4, num_warps=4),
@@ -866,7 +866,7 @@ def _int8_autotune_configs():
866866
triton.Config({'block_m': 64, 'block_n': 128, 'block_k': 32, 'group_size_m': 8}, num_stages=4, num_warps=4),
867867
triton.Config({'block_m': 128, 'block_n': 32, 'block_k': 32, 'group_size_m': 8}, num_stages=4, num_warps=4),
868868
]
869-
rdna_configs = [
869+
gfx12_configs = [
870870
triton.Config({'block_m': 128, 'block_n': 256, 'block_k': 64, 'group_size_m': 8}, num_stages=2, num_warps=8),
871871
triton.Config({'block_m': 128, 'block_n': 128, 'block_k': 128, 'group_size_m': 8}, num_stages=2, num_warps=8),
872872
triton.Config({'block_m': 128, 'block_n': 128, 'block_k': 64, 'group_size_m': 8}, num_stages=2, num_warps=4),
@@ -878,11 +878,26 @@ def _int8_autotune_configs():
878878
triton.Config({'block_m': 64, 'block_n': 128, 'block_k': 64, 'group_size_m': 8, 'waves_per_eu': 1}, num_stages=2, num_warps=4),
879879
triton.Config({'block_m': 64, 'block_n': 64, 'block_k': 64, 'group_size_m': 4, 'waves_per_eu': 1}, num_stages=2, num_warps=4),
880880
]
881-
return default_configs, rdna_configs
882-
883-
884-
_INT8_DEFAULT_CONFIGS, _INT8_RDNA_CONFIGS = _int8_autotune_configs()
885-
_INT8_MATMUL_CONFIGS = _INT8_DEFAULT_CONFIGS + _INT8_RDNA_CONFIGS
881+
gfx11_configs = list(gfx12_configs)
882+
gfx11_configs[6] = triton.Config(
883+
{'block_m': 64, 'block_n': 64, 'block_k': 128,
884+
'group_size_m': 4, 'waves_per_eu': 1},
885+
num_stages=2,
886+
num_warps=8,
887+
)
888+
return default_configs, gfx11_configs, gfx12_configs
889+
890+
891+
(
892+
_INT8_DEFAULT_CONFIGS,
893+
_INT8_GFX11_CONFIGS,
894+
_INT8_GFX12_CONFIGS,
895+
) = _int8_autotune_configs()
896+
# Per-device pruning returns ten RDNA candidates. The decorator sees their
897+
# eleven-config union so no device pays to benchmark the other generation's tile.
898+
_INT8_MATMUL_CONFIGS = (
899+
_INT8_DEFAULT_CONFIGS + _INT8_GFX12_CONFIGS + [_INT8_GFX11_CONFIGS[6]]
900+
)
886901

887902

888903
def _prune_int8_autotune_configs(configs, named_args, **kwargs):
@@ -894,13 +909,23 @@ def _prune_int8_autotune_configs(configs, named_args, **kwargs):
894909
arch = torch.cuda.get_device_properties(args['device_index']).gcnArchName.split(":")[0]
895910
except Exception:
896911
return _INT8_DEFAULT_CONFIGS
897-
if not arch.startswith(("gfx11", "gfx12")):
912+
if arch.startswith("gfx11"):
913+
rdna_configs = _INT8_GFX11_CONFIGS
914+
elif arch.startswith("gfx12"):
915+
rdna_configs = _INT8_GFX12_CONFIGS
916+
else:
898917
return _INT8_DEFAULT_CONFIGS
899918

900-
rdna_configs = _INT8_RDNA_CONFIGS
901-
# BK128 was consistently slower for small-M calls on gfx1151.
919+
# This large tile was unstable for small-M calls on gfx1151.
902920
if args['m'] <= 128:
903-
rdna_configs = [config for config in rdna_configs if config.kwargs['block_k'] <= 64]
921+
rdna_configs = [
922+
config for config in rdna_configs
923+
if not (
924+
config.kwargs['block_m'] == 128
925+
and config.kwargs['block_n'] == 128
926+
and config.kwargs['block_k'] == 128
927+
)
928+
]
904929
return rdna_configs
905930

906931

@@ -913,13 +938,13 @@ def _prune_int8_autotune_configs(configs, named_args, **kwargs):
913938
}
914939

915940
@triton.autotune(**_INT8_AUTOTUNE_KWARGS)
916-
@triton.jit
941+
@triton.jit(do_not_specialize=["device_index"])
917942
def _int8_matmul_dequant_kernel(
918943
# Pointers
919944
a_ptr, b_ptr, c_ptr,
920945
a_scale_ptr, b_scale_ptr, bias_ptr,
921946
# Matrix Dimensions
922-
m, n, k, device_index: tl.constexpr,
947+
m, n, k, device_index,
923948
# Strides
924949
stride_am, stride_ak,
925950
stride_bk, stride_bn,
@@ -985,13 +1010,13 @@ def _int8_matmul_dequant_kernel(
9851010
tl.store(c_ptrs, c, mask=c_mask)
9861011

9871012
@triton.autotune(**_INT8_AUTOTUNE_KWARGS)
988-
@triton.jit
1013+
@triton.jit(do_not_specialize=["device_index"])
9891014
def _int8_matmul_dequant_per_row_kernel(
9901015
# Pointers
9911016
a_ptr, b_ptr, c_ptr,
9921017
a_scale_ptr, b_scale_ptr, bias_ptr,
9931018
# Matrix Dimensions
994-
m, n, k, device_index: tl.constexpr,
1019+
m, n, k, device_index,
9951020
# Strides
9961021
stride_am, stride_ak,
9971022
stride_bk, stride_bn,

tests/test_int8.py

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -230,16 +230,17 @@ def record_call(*args, **kwargs):
230230
"hip_version,arches,device_index,m,expected_pool",
231231
[
232232
(None, ["gfx1100"], 0, 1024, "default"),
233-
("7.2", ["gfx1100"], 0, 1024, "rdna"),
234-
("7.2", ["gfx1151"], 0, 1024, "rdna"),
235-
("7.2", ["gfx1201"], 0, 1024, "rdna"),
236-
("7.2", ["gfx1100"], 0, 128, "rdna-small-m"),
237-
("7.2", ["gfx1100"], 0, 129, "rdna"),
233+
("7.2", ["gfx1100"], 0, 1024, "gfx11"),
234+
("7.2", ["gfx1151"], 0, 1024, "gfx11"),
235+
("7.2", ["gfx1201"], 0, 1024, "gfx12"),
236+
("7.2", ["gfx1100"], 0, 128, "gfx11-small-m"),
237+
("7.2", ["gfx1201"], 0, 128, "gfx12-small-m"),
238+
("7.2", ["gfx1100"], 0, 129, "gfx11"),
238239
("7.2", ["gfx908"], 0, 1024, "default"),
239240
("7.2", ["gfx90a"], 0, 1024, "default"),
240241
("7.2", ["gfx942"], 0, 1024, "default"),
241242
("7.2", ["gfx950"], 0, 1024, "default"),
242-
("7.2", ["gfx1100", "gfx90a"], 0, 1024, "rdna"),
243+
("7.2", ["gfx1100", "gfx90a"], 0, 1024, "gfx11"),
243244
("7.2", ["gfx1100", "gfx90a"], 1, 1024, "default"),
244245
("7.2", ["gfx1300"], 0, 1024, "default"),
245246
],
@@ -263,12 +264,24 @@ def test_int8_autotune_configs_are_device_scoped(
263264
m=m,
264265
)
265266

266-
if expected_pool == "rdna":
267-
assert configs == quantization._INT8_RDNA_CONFIGS
268-
elif expected_pool == "rdna-small-m":
267+
expected_configs = {
268+
"gfx11": quantization._INT8_GFX11_CONFIGS,
269+
"gfx12": quantization._INT8_GFX12_CONFIGS,
270+
}
271+
if expected_pool in expected_configs:
272+
assert configs == expected_configs[expected_pool]
273+
elif expected_pool.endswith("-small-m"):
274+
full_pool = expected_configs[expected_pool.removesuffix("-small-m")]
269275
assert len(configs) == 9
270-
assert all(config in quantization._INT8_RDNA_CONFIGS for config in configs)
271-
assert all(config.kwargs["block_k"] <= 64 for config in configs)
276+
assert all(config in full_pool for config in configs)
277+
if expected_pool.startswith("gfx11"):
278+
assert any(config.kwargs["block_k"] == 128 for config in configs)
279+
assert not any(
280+
config.kwargs["block_m"] == 128
281+
and config.kwargs["block_n"] == 128
282+
and config.kwargs["block_k"] == 128
283+
for config in configs
284+
)
272285
else:
273286
signatures = [
274287
(config.kwargs, config.num_stages, config.num_warps)
@@ -302,7 +315,7 @@ def test_int8_autotune_configs_isolate_heterogeneous_devices(monkeypatch):
302315
quantization._INT8_MATMUL_CONFIGS, {}, device_index=0, m=1024
303316
)
304317

305-
assert rdna_configs == quantization._INT8_RDNA_CONFIGS
318+
assert rdna_configs == quantization._INT8_GFX11_CONFIGS
306319
assert cdna_configs == quantization._INT8_DEFAULT_CONFIGS
307320
assert rdna_configs_again == rdna_configs
308321

@@ -336,10 +349,13 @@ def test_int8_autotune_pool_creation_does_not_probe_devices(monkeypatch):
336349
lambda _: (_ for _ in ()).throw(AssertionError("unexpected device probe")),
337350
)
338351

339-
default_configs, rdna_configs = quantization._int8_autotune_configs()
352+
default_configs, gfx11_configs, gfx12_configs = quantization._int8_autotune_configs()
340353

341354
assert len(default_configs) == 6
342-
assert len(rdna_configs) == 10
355+
assert len(gfx11_configs) == 10
356+
assert len(gfx12_configs) == 10
357+
assert len(quantization._INT8_MATMUL_CONFIGS) == 17
358+
assert gfx11_configs[6] != gfx12_configs[6]
343359

344360

345361
def test_int8_autotune_cache_key_includes_device():
@@ -351,8 +367,14 @@ def test_int8_autotune_cache_key_includes_device():
351367
"prune_configs_by": quantization._INT8_PRUNE_CONFIGS_BY,
352368
}
353369

354-
assert "device_index" in quantization._int8_matmul_dequant_kernel.keys
355-
assert "device_index" in quantization._int8_matmul_dequant_per_row_kernel.keys
370+
for kernel in (
371+
quantization._int8_matmul_dequant_kernel,
372+
quantization._int8_matmul_dequant_per_row_kernel,
373+
):
374+
assert "device_index" in kernel.keys
375+
device_index = kernel.fn.params[kernel.fn.arg_names.index("device_index")]
376+
assert not device_index.is_constexpr
377+
assert device_index.do_not_specialize
356378

357379

358380
# =============================================================================

0 commit comments

Comments
 (0)