diff --git a/README.md b/README.md index bfaeae7d6e..0d21cd8b85 100644 --- a/README.md +++ b/README.md @@ -302,7 +302,7 @@ For detailed documentation, see the [TileIR Backend Guide](docs/tileir_backend.m ## CuTe Backend (CUDA 13+) -Helion has an experimental [CUTLASS CuTe DSL](https://github.com/NVIDIA/cutlass) backend that lowers kernels through CuTe instead of Triton. +Helion has a beta [CUTLASS CuTe DSL](https://github.com/NVIDIA/cutlass) backend that lowers kernels through CuTe instead of Triton. **Requirements:** PyTorch must be built against **CUDA 13 or later** (`torch.version.cuda >= "13"`). The backend will refuse to launch on older CUDA builds. diff --git a/docs/installation.md b/docs/installation.md index 864a0fabcc..2264107be2 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -177,7 +177,7 @@ make html ### CuTe Backend (CUDA 13+) -To use the experimental [CUTLASS CuTe DSL](https://github.com/NVIDIA/cutlass) +To use the beta [CUTLASS CuTe DSL](https://github.com/NVIDIA/cutlass) backend (`HELION_BACKEND=cute`), PyTorch must be built against **CUDA 13 or later** (`torch.version.cuda >= "13"`). The backend refuses to launch on older CUDA builds. diff --git a/helion/_compiler/backend.py b/helion/_compiler/backend.py index 00b93b0e11..ddbb14c8f1 100644 --- a/helion/_compiler/backend.py +++ b/helion/_compiler/backend.py @@ -3,6 +3,7 @@ import abc import collections import dataclasses +import enum import functools import logging import math @@ -179,6 +180,14 @@ def _validate_subscript_indices(index: list[object]) -> int: return narrowed +class BackendState(enum.Enum): + """Maturity of a codegen backend.""" + + EXPERIMENTAL = "experimental" # Warns on use + BETA = "beta" # No warning, but no backwards-compat guarantee + STABLE = "stable" + + class Backend(abc.ABC): """Abstract base class for Helion code generation backends. @@ -195,9 +204,9 @@ def name(self) -> str: ... @property - def experimental(self) -> bool: - """Whether this backend is experimental and should emit a warning.""" - return True + def state(self) -> BackendState: + """Maturity of this backend; experimental backends emit a warning.""" + return BackendState.EXPERIMENTAL @property def supports_debug_dtype_asserts(self) -> bool: diff --git a/helion/_compiler/compile_environment.py b/helion/_compiler/compile_environment.py index 462b83ec34..3c95edeadb 100644 --- a/helion/_compiler/compile_environment.py +++ b/helion/_compiler/compile_environment.py @@ -40,6 +40,7 @@ from .._compat import target_device_capability from .._utils import triton_is_available from ..language.constexpr import ConstExpr +from .backend import BackendState from .backend_registry import get_backend_class from .source_location import SourceLocation from .source_location import current_location @@ -450,7 +451,7 @@ def __init__( "debug_dtype_asserts=True (it emits Triton tl.cast / " "tl.static_assert checks)", ) - if self._backend.experimental: + if self._backend.state is BackendState.EXPERIMENTAL: from torch._dynamo.utils import warn_once warn_once( diff --git a/helion/_compiler/cute/backend.py b/helion/_compiler/cute/backend.py index b4b6f1b231..b095e93034 100644 --- a/helion/_compiler/cute/backend.py +++ b/helion/_compiler/cute/backend.py @@ -23,6 +23,7 @@ from ... import exc from ..backend import Backend +from ..backend import BackendState from ..backend import _active_loop_block_ids from ..backend import _attention_flash_gate_enabled from ..backend import _attention_flash_supported @@ -1409,6 +1410,10 @@ def codegen_config(self, config: Config) -> Config: def name(self) -> str: return "cute" + @property + def state(self) -> BackendState: + return BackendState.BETA + @property def supports_eager_prepared_call(self) -> bool: return True diff --git a/helion/_compiler/flydsl/backend.py b/helion/_compiler/flydsl/backend.py index 55a80ed65a..e320caa40d 100644 --- a/helion/_compiler/flydsl/backend.py +++ b/helion/_compiler/flydsl/backend.py @@ -14,6 +14,7 @@ from ... import exc from ..ast_extension import expr_from_string from ..backend import Backend +from ..backend import BackendState if TYPE_CHECKING: import ast @@ -120,8 +121,8 @@ def name(self) -> str: return "flydsl" @property - def experimental(self) -> bool: - return True + def state(self) -> BackendState: + return BackendState.EXPERIMENTAL def validate_environment(self) -> None: try: diff --git a/helion/_compiler/metal/backend.py b/helion/_compiler/metal/backend.py index e3c4478619..f79031abab 100644 --- a/helion/_compiler/metal/backend.py +++ b/helion/_compiler/metal/backend.py @@ -12,6 +12,7 @@ from ... import exc from ..backend import Backend +from ..backend import BackendState from ..backend import _largest_divisor_at_most from ..cute.backend import CuteBackend from ._constants import MAX_THREAD_AXES @@ -78,6 +79,10 @@ def _get_dtype_to_metal() -> dict[torch.dtype, str]: def name(self) -> str: return "metal" + @property + def state(self) -> BackendState: + return BackendState.EXPERIMENTAL + def dtype_str(self, dtype: torch.dtype) -> str: dtype_map = self._get_dtype_to_metal() if dtype not in dtype_map: diff --git a/helion/_compiler/pallas/backend.py b/helion/_compiler/pallas/backend.py index 1cfbb32a87..24e32ed8b6 100644 --- a/helion/_compiler/pallas/backend.py +++ b/helion/_compiler/pallas/backend.py @@ -20,6 +20,7 @@ from ..ast_extension import expr_from_string from ..backend import AutotuneGridPolicy from ..backend import Backend +from ..backend import BackendState from ..backend import LauncherInfo from ..backend import _loop_contains_matmul from ..backend import _validate_subscript_indices @@ -274,6 +275,10 @@ class PallasBackend(Backend): def name(self) -> str: return "pallas" + @property + def state(self) -> BackendState: + return BackendState.BETA + @staticmethod # Overrides Backend.map_dot_precision. def map_dot_precision(precision: DotPrecision) -> str: diff --git a/helion/_compiler/triton/backend.py b/helion/_compiler/triton/backend.py index 871b066bd5..c8c5d6c6a0 100644 --- a/helion/_compiler/triton/backend.py +++ b/helion/_compiler/triton/backend.py @@ -18,6 +18,7 @@ from ... import _compat from ... import exc from ..backend import Backend +from ..backend import BackendState from ..backend import LauncherInfo from ..backend import log @@ -61,8 +62,8 @@ def name(self) -> str: return "triton" @property - def experimental(self) -> bool: - return False + def state(self) -> BackendState: + return BackendState.STABLE @property def supports_debug_dtype_asserts(self) -> bool: diff --git a/test/test_backend_registry.py b/test/test_backend_registry.py index 361cbda2aa..366e345f58 100644 --- a/test/test_backend_registry.py +++ b/test/test_backend_registry.py @@ -11,6 +11,7 @@ from helion._compiler import backend_registry from helion._compiler.aten_lowering import AtenLowering from helion._compiler.backend import Backend +from helion._compiler.backend import BackendState from helion._compiler.backend_registry import _REGISTRY from helion._compiler.backend_registry import all_reserved_launch_param_names from helion._compiler.backend_registry import get_backend_class @@ -90,8 +91,8 @@ def library_imports(self) -> dict[str, str]: try: self.assertIn("_test_custom", list_backends()) self.assertIs(get_backend_class("_test_custom"), _TestBackend) - # custom backends default to experimental=True - self.assertTrue(_TestBackend().experimental) + # custom backends default to experimental + self.assertIs(_TestBackend().state, BackendState.EXPERIMENTAL) finally: _REGISTRY.pop("_test_custom", None)