[rocprofiler-compute] Threshold Based Clamping in Analyze Stage (#2565)
* add threshold clamping function + parse in parser.py (with I/O) * implemented hybrid threshold solution * update changelog * removed absolute threshold hybrid approach; restored relative threshold + warn * edited warning msg, threshold -> 1% * update changelog * added 2 test cases * ran master workflow yaml config files * added to FAQ * Revert "ran master workflow yaml config files" This reverts commit 75a670e14d6f1619ebbda0ec218755ccbe0d22b1. * update FAQ * update config hashes * Broke down long functions into Class with sub-functions * ruff format * addressed comments
This commit is contained in:
committed by
GitHub
parent
7af2dba741
commit
69281bbcf4
@@ -7844,3 +7844,130 @@ def test_validate_roofline_csv_invalid_inconsistent_columns():
|
||||
assert is_valid is False
|
||||
assert "Inconsistent row length" in error_msg
|
||||
assert "row 2" in error_msg
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# TESTS FOR NOISE_CLAMP: Multi-Pass Profiling Variance Handling
|
||||
# =============================================================================
|
||||
|
||||
|
||||
@pytest.mark.noise_clamp
|
||||
def test_noise_clamp_clamping_behavior():
|
||||
"""Core behavior: positives unchanged, negatives clamped to 0."""
|
||||
import numpy as np
|
||||
|
||||
from utils.parser import to_noise_clamp
|
||||
|
||||
# Scalar: positive unchanged
|
||||
assert to_noise_clamp(1000.0, 100000.0) == 1000.0
|
||||
# Scalar: negative clamped
|
||||
assert to_noise_clamp(-100.0, 1000000.0) == 0.0
|
||||
|
||||
# Series: mixed values
|
||||
diff = pd.Series([100.0, -50.0, 200.0, -100.0])
|
||||
ref = pd.Series([1e6, 1e6, 1e6, 1e6])
|
||||
result = to_noise_clamp(diff, ref)
|
||||
pd.testing.assert_series_equal(result, pd.Series([100.0, 0.0, 200.0, 0.0]))
|
||||
|
||||
# NumPy array
|
||||
diff_np = np.array([100.0, -50.0])
|
||||
ref_np = np.array([1e6, 1e6])
|
||||
result_np = to_noise_clamp(diff_np, ref_np)
|
||||
np.testing.assert_array_equal(result_np, np.array([100.0, 0.0]))
|
||||
|
||||
|
||||
@pytest.mark.noise_clamp
|
||||
def test_noise_clamp_zero_reference():
|
||||
"""Edge case: zero reference should not cause division by zero."""
|
||||
from utils.parser import to_noise_clamp
|
||||
|
||||
assert to_noise_clamp(-100.0, 0.0) == 0.0
|
||||
result = to_noise_clamp(pd.Series([-100.0]), pd.Series([0.0]))
|
||||
assert result.iloc[0] == 0.0
|
||||
|
||||
|
||||
@pytest.mark.noise_clamp
|
||||
def test_noise_clamp_warning_above_threshold():
|
||||
"""Warning recorded when relative error >= 1%."""
|
||||
from utils.parser import (
|
||||
clear_noise_clamp_warnings,
|
||||
get_noise_clamp_warnings,
|
||||
to_noise_clamp,
|
||||
)
|
||||
|
||||
clear_noise_clamp_warnings()
|
||||
|
||||
# 2% error (above 1% threshold) - should record
|
||||
to_noise_clamp(pd.Series([-20000.0]), pd.Series([1000000.0]))
|
||||
|
||||
stats = get_noise_clamp_warnings()
|
||||
assert stats["count"] == 1
|
||||
assert stats["max_rel"] >= 0.01
|
||||
|
||||
|
||||
@pytest.mark.noise_clamp
|
||||
def test_noise_clamp_no_warning_below_threshold():
|
||||
"""No warning when relative error < 1%."""
|
||||
from utils.parser import (
|
||||
clear_noise_clamp_warnings,
|
||||
get_noise_clamp_warnings,
|
||||
to_noise_clamp,
|
||||
)
|
||||
|
||||
clear_noise_clamp_warnings()
|
||||
|
||||
# 0.5% error (below 1% threshold) - still clamped, no warning
|
||||
result = to_noise_clamp(pd.Series([-5000.0]), pd.Series([1000000.0]))
|
||||
assert result.iloc[0] == 0.0
|
||||
assert get_noise_clamp_warnings()["count"] == 0
|
||||
|
||||
|
||||
@pytest.mark.noise_clamp
|
||||
def test_noise_clamp_empty_input():
|
||||
"""Empty inputs should return empty without error."""
|
||||
from utils.parser import to_noise_clamp
|
||||
|
||||
result = to_noise_clamp(pd.Series([], dtype=float), pd.Series([], dtype=float))
|
||||
assert len(result) == 0
|
||||
|
||||
|
||||
@pytest.mark.noise_clamp
|
||||
def test_noise_clamp_threshold_boundary():
|
||||
"""Exactly 1% error should trigger warning (>= not >)."""
|
||||
from utils.parser import (
|
||||
clear_noise_clamp_warnings,
|
||||
get_noise_clamp_warnings,
|
||||
to_noise_clamp,
|
||||
)
|
||||
|
||||
clear_noise_clamp_warnings()
|
||||
|
||||
# Exactly 1% error: -10000 / 1000000 = 0.01
|
||||
to_noise_clamp(pd.Series([-10000.0]), pd.Series([1000000.0]))
|
||||
assert get_noise_clamp_warnings()["count"] == 1
|
||||
|
||||
|
||||
@pytest.mark.noise_clamp
|
||||
def test_noise_clamper_instance_isolation():
|
||||
"""Separate NoiseClamper instances should have independent state."""
|
||||
import numpy as np
|
||||
|
||||
from utils.parser import NoiseClamper
|
||||
|
||||
clamper1 = NoiseClamper()
|
||||
clamper2 = NoiseClamper()
|
||||
|
||||
clamper1.clamp(pd.Series([-20000.0]), pd.Series([1000000.0]))
|
||||
|
||||
assert clamper1.get_stats()["count"] == 1
|
||||
assert clamper2.get_stats()["count"] == 0
|
||||
|
||||
clamper1.clear()
|
||||
assert clamper1.get_stats()["count"] == 0
|
||||
assert clamper2.get_stats()["count"] == 0
|
||||
|
||||
clamper1.clamp(np.array([-50000.0]), np.array([1000000.0]))
|
||||
clamper2.clamp(np.array([-30000.0, -40000.0]), np.array([1000000.0, 1000000.0]))
|
||||
|
||||
assert clamper1.get_stats()["count"] == 1
|
||||
assert clamper2.get_stats()["count"] == 2
|
||||
|
||||
Reference in New Issue
Block a user