From 9c699f53c9153a2bed009a854d2f06da83a7d3d4 Mon Sep 17 00:00:00 2001 From: 0z5a Date: Tue, 3 Nov 2026 15:10:45 +0100 Subject: [PATCH] Reject opt_level=None when the kernel is defined _validate_opt_level let None through (also inside ByTarget), and the kernel signature advertised None, but opt_level_for_target asserts an int. So ct.kernel(opt_level=None) or ByTarget(sm_90=None) was accepted and then failed with a bare AssertionError when the cubin was compiled. Require an integer in [0, 3] and drop None from the signature. Signed-off-by: 0z5a --- changelog.d/opt-level-none.md | 2 ++ src/cuda/tile/_compiler_options.py | 7 +++---- src/cuda/tile/_execution.py | 2 +- test/test_compiler_options.py | 7 +++++++ 4 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 changelog.d/opt-level-none.md diff --git a/changelog.d/opt-level-none.md b/changelog.d/opt-level-none.md new file mode 100644 index 00000000..ed3e7162 --- /dev/null +++ b/changelog.d/opt-level-none.md @@ -0,0 +1,2 @@ +- `opt_level=None` (including inside `ByTarget`) is now rejected with a `ValueError` + when the kernel is defined, instead of failing with an `AssertionError` at compile time. diff --git a/src/cuda/tile/_compiler_options.py b/src/cuda/tile/_compiler_options.py index 152aacff..4d6ead1c 100644 --- a/src/cuda/tile/_compiler_options.py +++ b/src/cuda/tile/_compiler_options.py @@ -72,10 +72,9 @@ def _validate_occupancy(occupancy: None | int): raise ValueError(f'occupancy should be [1, 32], got {occupancy}') -def _validate_opt_level(opt_level: None | int): - if opt_level is not None: - if opt_level < 0 or opt_level > 3: - raise ValueError(f'opt_level should be [0, 3], got {opt_level}') +def _validate_opt_level(opt_level: int): + if not isinstance(opt_level, int) or opt_level < 0 or opt_level > 3: + raise ValueError(f'opt_level should be an integer in [0, 3], got {opt_level!r}') def _validate_num_worker_warps(num_worker_warps: None | int): diff --git a/src/cuda/tile/_execution.py b/src/cuda/tile/_execution.py index 12f4cd46..dbc45e12 100644 --- a/src/cuda/tile/_execution.py +++ b/src/cuda/tile/_execution.py @@ -115,7 +115,7 @@ def __init__(self, /, *, num_ctas: None | int | ByTarget[int] = None, occupancy: None | int | ByTarget[int] = None, - opt_level: None | int | ByTarget[int] = 3, + opt_level: int | ByTarget[int] = 3, num_worker_warps: None | int | ByTarget[int] = None): if not isinstance(function, FunctionType): raise TypeError("`kernel` decorator must be applied to a Python function") diff --git a/test/test_compiler_options.py b/test/test_compiler_options.py index b9cbc223..3c81b2a4 100644 --- a/test/test_compiler_options.py +++ b/test/test_compiler_options.py @@ -85,6 +85,13 @@ def test_opt_level_for_target_default(): assert CompilerOptions().opt_level_for_target("sm_100") == 3 +@pytest.mark.parametrize("opt_level", [None, -1, 4, ct.ByTarget(sm_100=None), + ct.ByTarget(default=None)]) +def test_opt_level_rejects_invalid(opt_level): + with pytest.raises(ValueError, match=r"opt_level should be an integer in \[0, 3\]"): + CompilerOptions(opt_level=opt_level) + + def _tensor(): return torch.zeros(64, dtype=torch.float32, device='cuda:0')