Skip to content

Commit 1988de4

Browse files
committed
feat(plan): surface backend selection in ContractionPlan
Add `ContractionPlan.backend` reporting which executor will run the contraction — "nki" when strategy is matmul/bmm and neuronxcc is importable, else "pytorch". Resolves Phase 1 acceptance criterion that plan_contraction must report dispatch="nki" when shapes qualify. - trntensor/plan.py: new field + _backend_for() helper - tests/test_plan.py: test_backend_reports_nki_or_pytorch - docs/api/plan.md: documents the new field 45 CPU tests pass.
1 parent 5dc73de commit 1988de4

3 files changed

Lines changed: 39 additions & 3 deletions

File tree

docs/api/plan.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ plan.transA, plan.transB # whether to pre-transpose before matmul
2121
Dataclass with the fields above plus:
2222

2323
- `subscripts` — the original subscript string
24+
- `backend` — executor that will run the contraction: `"nki"` (when
25+
the strategy is `matmul`/`bmm` and `neuronxcc` is importable) or
26+
`"pytorch"`
2427
- `estimated_flops: int`
2528

2629
## `estimate_flops(subscripts, *operands) -> int`

tests/test_plan.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,23 @@ def test_batched_matmul_metadata(self):
6161
assert "j" in plan.contraction_indices
6262
assert "b" in plan.batch_indices
6363

64+
def test_backend_reports_nki_or_pytorch(self):
65+
"""`plan.backend` reports the executor that will run the contraction.
66+
67+
On Neuron hosts, matmul/bmm strategies report `"nki"`; on CPU they
68+
report `"pytorch"`. The torch fallback always reports `"pytorch"`.
69+
"""
70+
from trntensor.nki.dispatch import HAS_NKI
71+
72+
plan_mm = trntensor.plan_contraction(
73+
"ij,jk->ik", torch.randn(4, 3), torch.randn(3, 5)
74+
)
75+
plan_torch = trntensor.plan_contraction(
76+
"ij,jk,kl->il", torch.randn(3, 4), torch.randn(4, 5), torch.randn(5, 2)
77+
)
78+
assert plan_mm.backend == ("nki" if HAS_NKI else "pytorch")
79+
assert plan_torch.backend == "pytorch"
80+
6481

6582
class TestEstimateFlops:
6683

trntensor/plan.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
class ContractionPlan:
2424
"""Execution plan for a tensor contraction."""
2525
subscripts: str
26-
strategy: str # "matmul", "bmm", "torch", "nki"
26+
strategy: str # algorithm: "matmul" | "bmm" | "torch"
27+
backend: str = "pytorch" # executor: "nki" | "pytorch"
2728
transA: bool = False
2829
transB: bool = False
2930
contraction_indices: list[str] = field(default_factory=list)
@@ -32,15 +33,30 @@ class ContractionPlan:
3233
estimated_flops: int = 0
3334

3435

36+
def _backend_for(strategy: str) -> str:
37+
"""Resolve which executor will run a given strategy.
38+
39+
Returns ``"nki"`` only when the strategy maps to a NKI kernel
40+
(``matmul`` or ``bmm``) and ``neuronxcc`` is importable.
41+
"""
42+
if strategy in ("matmul", "bmm"):
43+
from .nki.dispatch import HAS_NKI
44+
if HAS_NKI:
45+
return "nki"
46+
return "pytorch"
47+
48+
3549
def plan_contraction(subscripts: str, *operands: torch.Tensor) -> ContractionPlan:
3650
"""Analyze contraction and select execution strategy."""
3751
input_str, output_str = _parse_subscripts(subscripts)
3852
input_indices = input_str.split(",")
3953

4054
if len(operands) == 2:
41-
return _plan_binary(subscripts, input_indices, output_str, operands)
55+
plan = _plan_binary(subscripts, input_indices, output_str, operands)
4256
else:
43-
return ContractionPlan(subscripts=subscripts, strategy="torch")
57+
plan = ContractionPlan(subscripts=subscripts, strategy="torch")
58+
plan.backend = _backend_for(plan.strategy)
59+
return plan
4460

4561

4662
def _parse_subscripts(subscripts: str) -> tuple[str, str]:

0 commit comments

Comments
 (0)