Skip to content
29 changes: 28 additions & 1 deletion mlir/utils/performance/tests/test_tuningRunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
ConfigState, TuningState, TuningStateFile, TunedConfigsCache, Options, get_state_filepath,
verify_mode_flags, format_error, get_config_class, get_git_commit_hash, NumaTopology, Operation,
NumaNodeLock, resolve_verify_mode, canonicalize_test_vector, DebugFileWriter, TuningResult,
tune_config)
attention_cpu_verify_flags, ATTENTION_F32_ABSDIFF_THRESHOLD, tune_config)
from perfRunner import ( # noqa: E402
GemmConfiguration, ConvConfiguration, AttentionConfiguration, ConvGemmConfiguration,
GemmGemmConfiguration, PerfConfiguration, canonicalize_config)
Expand Down Expand Up @@ -94,6 +94,33 @@ def test_invalid_raises(self):
verify_mode_flags("invalid")


class TestAttentionCpuVerifyFlags:
"""Tests for attention_cpu_verify_flags (f32 attention allclose-style relDiff gate)."""

@staticmethod
def _cfg(cls, dtype):
# Bypass the heavy __init__ (arch-db lookups); the helper only needs the type + datatype.
cfg = object.__new__(cls)
cfg.datatype = dtype
return cfg

def test_f32_attention_cpu_gets_absdiff_gate(self):
flags = attention_cpu_verify_flags(self._cfg(AttentionConfiguration, "f32"), "cpu")
assert flags == ["-absDiff_threshold", ATTENTION_F32_ABSDIFF_THRESHOLD]

def test_non_f32_attention_no_gate(self):
# f16/bf16 disable relDiff in rocmlir-gen and i8 uses integer verification.
for dt in ("f16", "bf16", "i8"):
assert attention_cpu_verify_flags(self._cfg(AttentionConfiguration, dt), "cpu") == []

def test_non_attention_op_no_gate(self):
assert attention_cpu_verify_flags(self._cfg(GemmConfiguration, "f32"), "cpu") == []

def test_non_cpu_mode_no_gate(self):
for mode in ("gpu", "none"):
assert attention_cpu_verify_flags(self._cfg(AttentionConfiguration, "f32"), mode) == []


class TestFormatError:
"""Tests for format_error."""

Expand Down
32 changes: 30 additions & 2 deletions mlir/utils/performance/tuningRunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,28 @@ def verify_mode_flags(verify_mode: str) -> str:
raise ValueError(f"Unknown verification mode: {verify_mode}")


# f32 attention CPU-verification tolerance.
#
# The GPU attention kernel runs a flash / online-softmax reduction whose accumulation order
# differs from the sequential CPU reference. In f32 this diverges by up to ~1e-2 on a small
# fraction of output elements while RMS and average stay ~1e-3 or better, so the result is
# numerically sound but trips the strict relDiff_threshold. Gate relDiff on an absolute
# tolerance (numpy/torch allclose style, via -absDiff_threshold) so this benign accumulation
# noise does not false-fail tuning; RMS and absDiff still catch real regressions. rocmlir-gen
# already disables relDiff for f16/bf16 and i8 uses integer verification, so only f32 needs
# this. Same mechanism used by parameterSweeps.py and mlir/test/e2e/PrAttentionF32.toml.
ATTENTION_F32_ABSDIFF_THRESHOLD = "5e-2"


def attention_cpu_verify_flags(config: PerfConfiguration, verify_mode: str) -> List[str]:
"""Extra rocmlir-gen flags for f32 attention CPU verification (allclose-style relDiff gate)."""
if verify_mode != "cpu":
return []
if isinstance(config, AttentionConfiguration) and getattr(config, "datatype", "") == "f32":
return ["-absDiff_threshold", ATTENTION_F32_ABSDIFF_THRESHOLD]
return []


def kill_process(proc: Optional[subprocess.Popen]) -> None:
"""Terminate a subprocess and wait for cleanup."""
if proc is None:
Expand Down Expand Up @@ -1292,8 +1314,14 @@ def verify_perfconfig(perfconfig: str, config: PerfConfiguration, paths: Paths,

command_line_options = config.generate_mlir_driver_commandline(options.rocmlir_gen_flags,
kernel_repeats=MLIR_N_REPEATS)
rocmlir_gen_command = [paths.mlir_paths.rocmlir_gen_path, '-print-verify-results=summary'
] + verify_mode_flags(verify_mode).split() + command_line_options.split()
# Append op/dtype-specific verification tolerances unless the user already set them explicitly
# (user --rocmlir-gen-flags live in command_line_options and must win).
extra_verify_flags = attention_cpu_verify_flags(config, verify_mode)
if extra_verify_flags and '-absDiff_threshold' in command_line_options:
extra_verify_flags = []
rocmlir_gen_command = ([paths.mlir_paths.rocmlir_gen_path, '-print-verify-results=summary'] +
verify_mode_flags(verify_mode).split() + extra_verify_flags +
command_line_options.split())

rocmlir_driver_command = [paths.mlir_paths.rocmlir_driver_path, '-c']

Expand Down
Loading