Merged
fix: reject non-finite quantization clamp values #28
fix: reject non-finite quantization clamp values #28
Merged
tianjunAdd on Oct 2
Total: 2 files changed+60-2
@@ -5,6 +5,7 @@ This module intentionally performs no device initialization at import time.
5 5 
6from __future__ import annotations6from __future__ import annotations
7 7 
8+import math
8import os9import os
9from functools import cache, lru_cache10from functools import cache, lru_cache
10 11 
@@ -143,8 +144,8 @@ def set_amax_clamp_for_quant(fmt: str, clamp_min_value: float) -> None:
143 144 
144 _validate_quant_format(fmt)145 _validate_quant_format(fmt)
145 value = float(clamp_min_value)146 value = float(clamp_min_value)
146- if value <= 0:147+ if not math.isfinite(value) or value <= 0:
147- raise ValueError(f'clamp_min_value must be positive, got {clamp_min_value}.')148+ raise ValueError(f'clamp_min_value must be finite and positive, got {clamp_min_value}.')
148 _quant_clamp_min_values[fmt] = value149 _quant_clamp_min_values[fmt] = value
149 150 
150 151 
@@ -0,0 +1,57 @@
1+# MIT License
2+#
3+# Copyright (c) 2026 ops-tilelang contributors
4+#
5+# Permission is hereby granted, free of charge, to any person obtaining a copy
6+# of this software and associated documentation files (the "Software"), to deal
7+# in the Software without restriction, including without limitation the rights
8+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+# copies of the Software, and to permit persons to whom the Software is
10+# furnished to do so, subject to the following conditions:
11+#
12+# The above copyright notice and this permission notice shall be included in all
13+# copies or substantial portions of the Software.
14+#
15+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+# SOFTWARE.
22+ 
23+import pytest
24+ 
25+from cann_ops_tilelang.config import (
26+ get_amax_clamp_for_quant,
27+ reset_runtime_config,
28+ set_amax_clamp_for_quant,
29+)
30+ 
31+ 
32+@pytest.fixture(autouse=True)
33+def reset_quant_config():
34+ reset_runtime_config()
35+ yield
36+ reset_runtime_config()
37+ 
38+ 
39+@pytest.mark.parametrize('fmt', ['e4m3', 'e2m1'])
40+@pytest.mark.parametrize('value', [float('nan'), float('inf'), -float('inf'), 0.0, -1.0])
41+def test_quant_clamp_rejects_invalid_values_without_changing_config(fmt, value):
42+ previous = get_amax_clamp_for_quant(fmt)
43+ with pytest.raises(ValueError, match='positive'):
44+ set_amax_clamp_for_quant(fmt, value)
45+ assert get_amax_clamp_for_quant(fmt) == previous
46+ 
47+ 
48+@pytest.mark.parametrize('fmt', ['e4m3', 'e2m1'])
49+@pytest.mark.parametrize('value', [1e-8, 1.0, 1e6])
50+def test_quant_clamp_accepts_positive_finite_values(fmt, value):
51+ set_amax_clamp_for_quant(fmt, value)
52+ assert get_amax_clamp_for_quant(fmt) == value
53+ 
54+ 
55+def test_quant_clamp_rejects_unsupported_format():
56+ with pytest.raises(ValueError, match='Unsupported quantization format'):
57+ set_amax_clamp_for_quant('unknown', 1.0)