mirror of
https://github.com/tile-ai/tilelang.git
synced 2026-10-24 07:04:00 +08:00
155 lines
5.5 KiB
Python
155 lines
5.5 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
import tilelang
|
|
from tvm.target import Target
|
|
import tilelang.backend.target as target_registry
|
|
from tilelang.backend.execution_backend import (
|
|
ExecutionBackendSpec,
|
|
allowed_backends_for_target,
|
|
register_execution_backend,
|
|
resolve_execution_backend,
|
|
)
|
|
from tilelang.backend.target import (
|
|
auto_detect_target,
|
|
determine_target,
|
|
list_target_detectors,
|
|
register_target_detector,
|
|
)
|
|
|
|
|
|
def test_tilelang_does_not_export_target_wrapper():
|
|
assert not hasattr(tilelang, "Target")
|
|
|
|
|
|
def test_default_target_env_accepts_json_string(monkeypatch):
|
|
monkeypatch.setenv("TILELANG_DEFAULT_TARGET", '{"kind": "cuda", "arch": "sm_100f", "code": ["sm_100a", "sm_103a"]}')
|
|
|
|
assert tilelang.env.get_default_target() == {
|
|
"kind": "cuda",
|
|
"arch": "sm_100f",
|
|
"code": ["sm_100a", "sm_103a"],
|
|
}
|
|
|
|
|
|
def test_default_target_env_rejects_unquoted_json_keys(monkeypatch):
|
|
monkeypatch.setenv("TILELANG_DEFAULT_TARGET", '{kind: "cuda", arch: "sm_100f"}')
|
|
|
|
with pytest.raises(ValueError, match="Use JSON syntax"):
|
|
tilelang.env.get_default_target()
|
|
|
|
|
|
def test_default_target_env_keeps_plain_string(monkeypatch):
|
|
monkeypatch.setenv("TILELANG_DEFAULT_TARGET", "cuda")
|
|
|
|
assert tilelang.env.get_default_target() == "cuda"
|
|
|
|
|
|
def test_bare_cuda_target_uses_detected_exact_arch(monkeypatch):
|
|
from tilelang.cuda import target as cuda_target
|
|
|
|
monkeypatch.setattr(cuda_target, "_detect_torch_cuda_arch", lambda: "sm_90a")
|
|
|
|
target = determine_target("cuda", return_object=True)
|
|
|
|
assert isinstance(target, Target)
|
|
assert target.kind.name == "cuda"
|
|
assert str(target.attrs["arch"]) == "sm_90a"
|
|
|
|
|
|
def test_cuda_target_code_attr_survives_target_normalization():
|
|
target = determine_target(
|
|
{"kind": "cuda", "arch": "sm_100f", "code": ["sm_100a", "sm_103a"]},
|
|
return_object=True,
|
|
)
|
|
|
|
assert isinstance(target, Target)
|
|
assert target.kind.name == "cuda"
|
|
assert str(target.attrs["arch"]) == "sm_100f"
|
|
assert list(target.attrs["code"]) == ["sm_100a", "sm_103a"]
|
|
assert list(target.export()["code"]) == ["sm_100a", "sm_103a"]
|
|
|
|
|
|
def test_cuda_target_code_attr_rejects_string_code():
|
|
with pytest.raises(AssertionError, match="valid target config dict"):
|
|
determine_target({"kind": "cuda", "arch": "sm_100f", "code": "sm_100a"}, return_object=True)
|
|
|
|
|
|
def test_cuda_target_rejects_compute_arch():
|
|
with pytest.raises(AssertionError, match="valid target config dict"):
|
|
determine_target({"kind": "cuda", "arch": "compute_90"}, return_object=True)
|
|
|
|
|
|
def test_auto_target_uses_registered_detectors():
|
|
name = "unit-auto-target"
|
|
old_detectors = dict(target_registry._TARGET_DETECTORS)
|
|
try:
|
|
target_registry._TARGET_DETECTORS.clear()
|
|
register_target_detector(name, lambda: Target({"kind": "llvm", "mcpu": "native"}), override=True)
|
|
|
|
target = auto_detect_target()
|
|
|
|
assert isinstance(target, Target)
|
|
assert target.kind.name == "llvm"
|
|
assert str(target.attrs["mcpu"]) == "native"
|
|
assert name in list_target_detectors()
|
|
finally:
|
|
target_registry._TARGET_DETECTORS.clear()
|
|
target_registry._TARGET_DETECTORS.update(old_detectors)
|
|
|
|
|
|
def test_auto_target_detector_falls_through_none_result():
|
|
first_name = "unit-auto-none"
|
|
second_name = "unit-auto-fallback"
|
|
old_detectors = dict(target_registry._TARGET_DETECTORS)
|
|
try:
|
|
target_registry._TARGET_DETECTORS.clear()
|
|
register_target_detector(first_name, lambda: None, override=True)
|
|
register_target_detector(second_name, lambda: "llvm", override=True)
|
|
|
|
assert auto_detect_target() == "llvm"
|
|
assert list_target_detectors() == (first_name, second_name)
|
|
finally:
|
|
target_registry._TARGET_DETECTORS.clear()
|
|
target_registry._TARGET_DETECTORS.update(old_detectors)
|
|
|
|
|
|
def test_execution_backend_registry_resolves_target_policy():
|
|
target_kind = "llvm"
|
|
target = Target({"kind": target_kind})
|
|
from tilelang.backend import execution_backend as backend_registry
|
|
|
|
old_execution_specs = backend_registry._EXECUTION_BACKENDS.get(target_kind)
|
|
was_loaded = target_kind in backend_registry._LOADED_EXECUTION_BACKENDS
|
|
try:
|
|
backend_registry._EXECUTION_BACKENDS[target_kind] = []
|
|
backend_registry._LOADED_EXECUTION_BACKENDS.add(target_kind)
|
|
register_execution_backend(target_kind, ExecutionBackendSpec("fast"), override=True)
|
|
register_execution_backend(target_kind, ExecutionBackendSpec("slow"), override=True)
|
|
|
|
assert allowed_backends_for_target(target) == ["fast", "slow"]
|
|
assert resolve_execution_backend("auto", target) == "fast"
|
|
assert resolve_execution_backend("slow", target) == "slow"
|
|
finally:
|
|
if old_execution_specs is None:
|
|
backend_registry._EXECUTION_BACKENDS.pop(target_kind, None)
|
|
else:
|
|
backend_registry._EXECUTION_BACKENDS[target_kind] = old_execution_specs
|
|
if not was_loaded:
|
|
backend_registry._LOADED_EXECUTION_BACKENDS.discard(target_kind)
|
|
|
|
|
|
def test_execution_backend_registry_rejects_invalid_backend():
|
|
target = Target("llvm")
|
|
|
|
with pytest.raises(ValueError, match="Invalid execution backend"):
|
|
resolve_execution_backend("nvrtc", target)
|
|
|
|
|
|
def test_execution_backend_registry_rejects_removed_dlpack_backend():
|
|
target = Target("llvm")
|
|
|
|
with pytest.raises(ValueError, match="Invalid execution backend 'dlpack'"):
|
|
resolve_execution_backend("dlpack", target)
|