Merged
fix: reject non-finite quantization clamp values #28
tianjunAdd on Oct 2
fix: reject non-finite quantization clamp values #28
Merged
Total: 2 files changed+60-2
| @@ -5,6 +5,7 @@ This module intentionally performs no device initialization at import time. | |||
| 5 | 5 | ||
| 6 | from __future__ import annotations | 6 | from __future__ import annotations |
| 7 | 7 | ||
| 8 | +import math | ||
| 8 | import os | 9 | import os |
| 9 | from functools import cache, lru_cache | 10 | from 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] = value | 149 | _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) | ||