meta.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. """Op metadata contract for b12x.
  2. Every op directory's ``__init__.py`` is exactly: a docstring, an ``OpMeta``
  3. named ``META``, a ``TYPE_CHECKING`` import block, and one call to
  4. :func:`install_lazy_api`. The registry test enforces the shape.
  5. This module must stay stdlib-only: op ``__init__`` files import it at
  6. namespace-import time, which must not pull torch/cutlass/triton.
  7. """
  8. from __future__ import annotations
  9. import importlib
  10. from dataclasses import dataclass, field
  11. from typing import Any, Literal
  12. @dataclass(frozen=True, kw_only=True)
  13. class Provenance:
  14. """Where an op's code came from (auditable against upstream forever)."""
  15. repo: str
  16. commit: str
  17. paths: tuple[str, ...]
  18. @dataclass(frozen=True, kw_only=True)
  19. class OpMeta:
  20. """Machine-readable header describing one experimental op.
  21. ``api_style`` declares the op's lifecycle contract:
  22. - ``planned``: ``Caps -> plan() -> bind() -> run*()``; ``plan`` is
  23. host-side and may allocate, ``bind`` only creates views (allocation
  24. free), ``run*`` is CUDA-graph-capture safe.
  25. - ``oneshot``: plain functions with domain verbs (``mm``, ``quantize``).
  26. - ``stateful``: long-lived class instances (comm collectives).
  27. """
  28. name: str
  29. group: str
  30. api_style: Literal["planned", "oneshot", "stateful"]
  31. entry_points: tuple[str, ...]
  32. archs: tuple[str, ...] = ("sm120a", "sm121a")
  33. dtypes: tuple[str, ...] = ()
  34. recipes: tuple[str, ...] = ()
  35. requires: tuple[str, ...] = ()
  36. status: Literal["experimental"] = "experimental"
  37. provenance: Provenance = field(
  38. default_factory=lambda: Provenance(repo="", commit="", paths=())
  39. )
  40. test_path: str = ""
  41. since: str = ""
  42. notes: str = ""
  43. @property
  44. def qualname(self) -> str:
  45. return f"{self.group}.{self.name}"
  46. def install_lazy_api(module_globals: dict[str, Any], meta: OpMeta) -> None:
  47. """Wire an op module's lazy public surface from its ``META``.
  48. Installs PEP 562 ``__getattr__``/``__dir__`` plus ``__all__`` so that
  49. every entry point resolves from the op's ``api`` module on first access.
  50. Importing the op module itself therefore stays side-effect free (no
  51. cutlass/triton import, no torch custom-op registration).
  52. """
  53. module_name = module_globals["__name__"]
  54. def __getattr__(name: str) -> Any:
  55. if name in meta.entry_points:
  56. api = importlib.import_module(".api", module_name)
  57. value = getattr(api, name)
  58. module_globals[name] = value
  59. return value
  60. raise AttributeError(f"module {module_name!r} has no attribute {name!r}")
  61. def __dir__() -> list[str]:
  62. return sorted([*meta.entry_points, "META"])
  63. module_globals["__getattr__"] = __getattr__
  64. module_globals["__dir__"] = __dir__
  65. module_globals["__all__"] = [*meta.entry_points, "META"]
  66. __all__ = ["OpMeta", "Provenance", "install_lazy_api"]