trntensor 0.3.0__tar.gz → 0.17.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- trntensor-0.17.0/CHANGELOG.md +686 -0
- {trntensor-0.3.0/trntensor.egg-info → trntensor-0.17.0}/PKG-INFO +6 -5
- {trntensor-0.3.0 → trntensor-0.17.0}/README.md +5 -4
- trntensor-0.17.0/docs/api/decompose.md +106 -0
- trntensor-0.17.0/docs/api/einsum.md +175 -0
- trntensor-0.17.0/docs/api/plan.md +96 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/api/quantum.md +1 -1
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/architecture.md +34 -3
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/contraction_patterns.md +7 -8
- trntensor-0.17.0/docs/design/matmul_dispatch_findings.md +149 -0
- trntensor-0.17.0/docs/design/matmul_kernel_profile.md +159 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/quickstart.md +6 -6
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/tutorial_df_mp2.md +2 -4
- {trntensor-0.3.0 → trntensor-0.17.0}/infra/terraform/main.tf +3 -1
- {trntensor-0.3.0 → trntensor-0.17.0}/pyproject.toml +5 -2
- trntensor-0.17.0/scripts/autotune_dispatch.py +233 -0
- trntensor-0.17.0/scripts/run_neuron_profile.sh +469 -0
- trntensor-0.17.0/scripts/run_reduce_parallel_multirank.py +527 -0
- trntensor-0.17.0/tests/conftest.py +43 -0
- trntensor-0.17.0/tests/test_einsum.py +788 -0
- trntensor-0.17.0/tests/test_nki_compile.py +91 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/tests/test_nki_kernels.py +54 -7
- {trntensor-0.3.0 → trntensor-0.17.0}/tests/test_nki_sim.py +111 -1
- trntensor-0.17.0/tests/test_parallel.py +451 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/tests/test_plan.py +27 -1
- trntensor-0.17.0/tests/test_sr_runtime.py +163 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/trntensor/__init__.py +9 -1
- trntensor-0.17.0/trntensor/einsum.py +637 -0
- trntensor-0.17.0/trntensor/nki/_kernels.py +362 -0
- trntensor-0.17.0/trntensor/nki/collectives.py +97 -0
- trntensor-0.17.0/trntensor/nki/dispatch.py +547 -0
- trntensor-0.17.0/trntensor/parallel.py +327 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/trntensor/plan.py +178 -8
- {trntensor-0.3.0 → trntensor-0.17.0}/trntensor/quantum.py +4 -25
- {trntensor-0.3.0 → trntensor-0.17.0/trntensor.egg-info}/PKG-INFO +6 -5
- {trntensor-0.3.0 → trntensor-0.17.0}/trntensor.egg-info/SOURCES.txt +10 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/uv.lock +1 -1
- trntensor-0.3.0/CHANGELOG.md +0 -201
- trntensor-0.3.0/docs/api/decompose.md +0 -41
- trntensor-0.3.0/docs/api/einsum.md +0 -43
- trntensor-0.3.0/docs/api/plan.md +0 -36
- trntensor-0.3.0/tests/conftest.py +0 -12
- trntensor-0.3.0/tests/test_einsum.py +0 -293
- trntensor-0.3.0/trntensor/einsum.py +0 -228
- trntensor-0.3.0/trntensor/nki/_kernels.py +0 -296
- trntensor-0.3.0/trntensor/nki/dispatch.py +0 -343
- {trntensor-0.3.0 → trntensor-0.17.0}/.github/workflows/ci.yml +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/.github/workflows/notify-umbrella.yml +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/.github/workflows/publish.yml +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/.gitignore +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/.pre-commit-config.yaml +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/CLAUDE.md +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/CODE_OF_CONDUCT.md +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/CONTRIBUTING.md +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/LICENSE +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/benchmarks/__init__.py +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/benchmarks/bench_einsum.py +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/api/index.md +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/api/nki.md +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/aws_setup.md +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/benchmarks.md +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/developing_kernels.md +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/index.md +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/docs/installation.md +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/examples/df_mp2_einsum.py +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/infra/terraform/README.md +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/mkdocs.yml +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/scripts/bench_to_md.py +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/scripts/run_benchmarks.sh +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/scripts/run_neuron_tests.sh +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/scripts/run_simulator_tests.sh +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/setup.cfg +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/tests/test_decompose.py +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/tests/test_nki.py +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/tests/test_quantum.py +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/trntensor/decompose.py +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/trntensor/nki/__init__.py +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/trntensor/py.typed +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/trntensor.egg-info/dependency_links.txt +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/trntensor.egg-info/requires.txt +0 -0
- {trntensor-0.3.0 → trntensor-0.17.0}/trntensor.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.17.0] — 2026-10-28
|
|
11
|
+
|
|
12
|
+
Validated on Trn2 (trn2.3xlarge, Neuron SDK 2.33.0, native TorchNeuron device) — see trnsci/trnsci#35.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Reduce-parallel sharding on real multi-rank all-reduce (Phase 4 prototype).**
|
|
17
|
+
Before this change, reduce-parallel and mixed output/reduce-parallel einsums
|
|
18
|
+
raised `NotImplementedError` whenever `HAS_NKI` was true.
|
|
19
|
+
- Under an initialized `torch.distributed` group with
|
|
20
|
+
`world_size == n_shards > 1`, rank `r` now computes only shard `r`'s
|
|
21
|
+
partial on its own device. The partials are combined with a real
|
|
22
|
+
all-reduce. Single-process runs keep `_mock_allreduce`.
|
|
23
|
+
- The backend is chosen by `trntensor.parallel.allreduce_backend`. `auto`
|
|
24
|
+
selects `nki` under a `"neuron"` process group, `torch` under any other
|
|
25
|
+
group, and `mock` otherwise. Override it with
|
|
26
|
+
`TRNTENSOR_ALLREDUCE=mock|torch|nki|auto` or `parallel.set_allreduce_backend()`.
|
|
27
|
+
An explicit `torch`/`nki` request that cannot be honored raises
|
|
28
|
+
`RuntimeError`; it never falls back to replicated compute.
|
|
29
|
+
- `trntensor.nki.collectives.nki_all_reduce_sum` is an `@nki.jit` kernel
|
|
30
|
+
using `nki.collectives.all_reduce(op=add)` on named `shared_hbm` buffers,
|
|
31
|
+
invoked via `torch_neuronx.wrap_nki(k)[(lnc,)]`. This is the pattern
|
|
32
|
+
measured bit-exact on Trn2 (SDK 2.33, NKI 0.7.0, LNC=2) in trnsci spike B4.
|
|
33
|
+
`private_hbm` gave wrong values at LNC=2.
|
|
34
|
+
- `scripts/run_reduce_parallel_multirank.py` runs multi-rank checks: one
|
|
35
|
+
process per rank, core pinning, hard timeouts, and per-rank logs. It
|
|
36
|
+
checks `ij,jk->ik` with `j` sharded at n = 512–2048 against the
|
|
37
|
+
single-device result (fp32 rel err ≤ 1e-5) and requires all ranks to
|
|
38
|
+
agree. It also reports bit-exactness against a fixed-order sum, plus
|
|
39
|
+
timings. Pass `--cpu` for a gloo pre-flight. Rank cores must be an
|
|
40
|
+
aligned pair or quad (0-1, 2-3, 0-3).
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **Precision promises (Trn2 spike B5, #42).**
|
|
45
|
+
- `precision="kahan"` on Neuron-device (or other non-fp64) operands now
|
|
46
|
+
contracts on the host in true fp64 and moves the result back. Before,
|
|
47
|
+
the "fp64" einsum ran on the device, which has no fp64 datapath. On Trn2
|
|
48
|
+
fp32 results measured ~1.4 ulp (max componentwise 8.4e-8 at N=128),
|
|
49
|
+
above the K·2⁻⁵³ + u bound that a real fp64 accumulation plus one
|
|
50
|
+
rounding satisfies. The bound was right; the extra rounding was the bug.
|
|
51
|
+
- Error bounds now include the final rounding of the result to its dtype
|
|
52
|
+
(`u_out`): `"fast"` K·u + u_out, `"sr"` √K·u + u_out, `"dd"` K·u² + u_out,
|
|
53
|
+
`"kahan"` K·2⁻⁵³ + u_out. `select_precision_for_error` selects on these
|
|
54
|
+
bounds. When the target is below the floor (≈ 3.9e-3 for bf16 results,
|
|
55
|
+
6.0e-8 for fp32), it emits a one-time `RuntimeWarning` and returns
|
|
56
|
+
`"kahan"` instead of silently missing the target. It does not raise.
|
|
57
|
+
Targets below K·2⁻⁵³ still raise `ValueError`. Because of the `u_out`
|
|
58
|
+
term, some bf16 targets near 2⁻⁸ now select a more accurate mode than
|
|
59
|
+
before.
|
|
60
|
+
|
|
61
|
+
- **NKI 0.7 / neuronx-cc 2.28 kernel compile on Trn2 (#41).**
|
|
62
|
+
- `ao_to_mo_transform_kernel`: step 1 now computes the intermediate
|
|
63
|
+
already transposed (`eri` tile as the stationary operand, ν-major
|
|
64
|
+
scratch), so step 2 loads its stationary tile with a plain DMA. The
|
|
65
|
+
former `nl.load_transpose2d` of a strided HBM slice was rejected by the
|
|
66
|
+
BIR verifier (`checkDMATranspose`: "transposing dimensions should be
|
|
67
|
+
continuous"). The ν loop is now `TILE_K`-wide, so the dispatcher pads
|
|
68
|
+
`nbasis` to a multiple of 128 instead of 512.
|
|
69
|
+
- `mp2_energy_kernel`: removed the `(128, 1) → (1, 128)` reshape
|
|
70
|
+
("Partition dim size must be preserved") and the cross-partition
|
|
71
|
+
`nl.sum(axis=(0, 1))`. The dispatcher now passes `B` as
|
|
72
|
+
`(nocc, naux, nvir)` (plain loads, no DMA transposes) and ε_occ / ε_vir
|
|
73
|
+
pre-broadcast across the 128 partitions; the kernel row-reduces per
|
|
74
|
+
lane and finishes with a `accᵀ · ones` matmul on the Tensor Engine.
|
|
75
|
+
- `matmul_kernel` / `batched_matmul_kernel` `use_sr=True`: NKI 0.7's
|
|
76
|
+
`nisa.activation` has no `out_dtype` / `round_mode` kwargs; the
|
|
77
|
+
downcast now calls `nisa.activation(dst=..., op=nl.copy, data=psum)`.
|
|
78
|
+
Stochastic rounding is a runtime setting on this toolchain, not a
|
|
79
|
+
per-instruction one.
|
|
80
|
+
- `tests/test_nki_kernels.py`: replaced the stale `test_oversize_raises`
|
|
81
|
+
(nvir > 128 no longer raises since M-tiling landed) with a correctness
|
|
82
|
+
check at nvir = 200.
|
|
83
|
+
|
|
84
|
+
### Added
|
|
85
|
+
|
|
86
|
+
- `trntensor.forward_error_bound(mode, dtype, K)`: the componentwise error
|
|
87
|
+
bound each precision mode promises, including output rounding (#42).
|
|
88
|
+
- **Stochastic-rounding runtime guard (#41).** On NKI 0.7 (Neuron SDK
|
|
89
|
+
2.33) the `use_sr` flag no longer chooses the rounding mode. On Trn2,
|
|
90
|
+
with `NEURON_RT_STOCHASTIC_ROUNDING_EN` unset or `0`, both
|
|
91
|
+
`use_sr=True` and `use_sr=False` round to nearest even and are
|
|
92
|
+
deterministic. With `=1`, both round stochastically. The Neuron Runtime
|
|
93
|
+
sets the mode for the whole process when it initializes.
|
|
94
|
+
`nki_matmul` / `nki_batched_matmul` now emit a one-time `RuntimeWarning`
|
|
95
|
+
when SR is requested on the native NKI path without
|
|
96
|
+
`NEURON_RT_STOCHASTIC_ROUNDING_EN=1`, then still compute
|
|
97
|
+
(round-to-nearest). This covers `precision="sr"` in `einsum` /
|
|
98
|
+
`multi_einsum` and `target_forward_error=` when it picks `"sr"`. The CPU
|
|
99
|
+
fallback and `nki.simulate` paths are unaffected. New
|
|
100
|
+
`trntensor.nki.dispatch.sr_runtime_enabled()`.
|
|
101
|
+
- Docs (`docs/api/einsum.md`, `docs/api/plan.md`) and docstrings explain
|
|
102
|
+
that the variable has to be set at process start, and that with it set
|
|
103
|
+
*every* downcast in the process rounds stochastically, including
|
|
104
|
+
`precision="fast"`.
|
|
105
|
+
- Tests: `tests/test_sr_runtime.py` (CPU, native path stubbed);
|
|
106
|
+
hardware `TestStochasticRoundingRuntime` in `tests/test_nki_kernels.py`
|
|
107
|
+
(markers `neuron` + `neuron_sr`), gated by the `sr_runtime` fixture.
|
|
108
|
+
The fixture skips unless the variable was `1` at process start.
|
|
109
|
+
- `tests/test_nki_compile.py` (`nki_simulator` marker): runs the NKI
|
|
110
|
+
frontend (trace → MLIR → verify) on CPU for every kernel at trn1, trn2,
|
|
111
|
+
and trn2 lnc=2. Catches the verifier errors `nki.simulate` misses.
|
|
112
|
+
|
|
113
|
+
## [0.16.0] — 2026-04-29
|
|
114
|
+
|
|
115
|
+
### Added
|
|
116
|
+
|
|
117
|
+
- **`target_forward_error=` for `multi_einsum()`** — extends the automatic
|
|
118
|
+
precision contract from v0.15.0 to multi-contraction calls.
|
|
119
|
+
|
|
120
|
+
For the per-contraction fallback path, each ``einsum()`` call resolves its
|
|
121
|
+
own K independently, so heterogeneous contractions (different subscripts or
|
|
122
|
+
operand shapes) each get the cheapest mode that satisfies the target for
|
|
123
|
+
*their* K. For the homogeneous batching path (same subscript, same shapes),
|
|
124
|
+
the mode is resolved once from the first contraction's K and dtype — which
|
|
125
|
+
equals all others in the batch.
|
|
126
|
+
|
|
127
|
+
Mutually exclusive with explicit ``precision=``, same as ``einsum()``.
|
|
128
|
+
|
|
129
|
+
## [0.15.0] — 2026-04-27
|
|
130
|
+
|
|
131
|
+
### Added
|
|
132
|
+
|
|
133
|
+
- **`target_forward_error=` kwarg for `einsum()`** — automatic precision
|
|
134
|
+
selection. Instead of specifying a precision mode manually, callers supply
|
|
135
|
+
a relative forward error bound and trntensor picks the cheapest mode whose
|
|
136
|
+
theoretical error bound satisfies it:
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
einsum("ij,jk->ik", A, B, target_forward_error=1e-4)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Selection order (cheapest first): ``"fast"`` → ``"sr"`` → ``"dd"`` →
|
|
143
|
+
``"kahan"``. Error bounds used (Higham 2002 §3, Connolly–Higham–Mary 2021):
|
|
144
|
+
|
|
145
|
+
- ``"fast"``: K · u (Wilkinson worst-case)
|
|
146
|
+
- ``"sr"``: √K · u (expected; mean-zero — statistical, not worst-case)
|
|
147
|
+
- ``"dd"``: K · u² (Ozaki-2 worst-case)
|
|
148
|
+
- ``"kahan"``: K · u_f64 (FP64 Wilkinson worst-case)
|
|
149
|
+
|
|
150
|
+
Where K = product of contracted dimension sizes and u = unit roundoff for
|
|
151
|
+
the operand dtype (BF16: 2⁻⁸, FP16: 2⁻¹¹, FP32: 2⁻²⁴, FP64: 2⁻⁵³).
|
|
152
|
+
``"sr"`` and ``"dd"`` are only considered for BF16 and FP16 inputs.
|
|
153
|
+
|
|
154
|
+
Raises ``ValueError`` when both ``precision=`` and ``target_forward_error=``
|
|
155
|
+
are given, or when no available mode can achieve the target.
|
|
156
|
+
|
|
157
|
+
- **`select_precision_for_error(dtype, K, target_forward_error)`** — the
|
|
158
|
+
selector as a public API function (``trntensor.select_precision_for_error``).
|
|
159
|
+
Useful for inspecting which mode would be chosen without running the full
|
|
160
|
+
contraction.
|
|
161
|
+
|
|
162
|
+
### Notes
|
|
163
|
+
|
|
164
|
+
``target_forward_error=`` is a first step toward the suite-level
|
|
165
|
+
``target_forward_error`` contract described in the architecture brief. The
|
|
166
|
+
current implementation uses static bounds (Wilkinson/Connolly–Higham–Mary);
|
|
167
|
+
adaptive error estimation (measuring actual residuals) is future work.
|
|
168
|
+
|
|
169
|
+
## [0.14.0] — 2026-04-24
|
|
170
|
+
|
|
171
|
+
### Added
|
|
172
|
+
|
|
173
|
+
- **`precision="dd"` on CPU — Ozaki-2 splitting** — lifts the unconditional
|
|
174
|
+
``NotImplementedError`` for double-double accumulation on CPU.
|
|
175
|
+
|
|
176
|
+
``_ozaki_split_cpu(A, k)`` splits a FP32 tensor into ``k`` BF16-precision
|
|
177
|
+
summands using the Ogita–Rump–Oishi error-free split: at each step,
|
|
178
|
+
``s = round_bfloat16(remainder)`` and ``remainder -= s`` (exact by Sterbenz's
|
|
179
|
+
lemma since ``|remainder|/|s| ∈ [0.5, 2]``). ``_ozaki_matmul_cpu(A, B, k=2)``
|
|
180
|
+
computes ``k²`` FP32 matmuls of the summand pairs and sums in FP32, achieving
|
|
181
|
+
forward error O(K · u_bf² · |C|) vs O(K · u_bf · |C|) for a single BF16
|
|
182
|
+
matmul — substantially more accurate for large K.
|
|
183
|
+
|
|
184
|
+
On CPU (``HAS_NKI=False``): ``precision="dd"`` routes the ``matmul`` strategy
|
|
185
|
+
through ``_ozaki_matmul_cpu``; the ``path`` strategy propagates ``precision="dd"``
|
|
186
|
+
recursively so each binary matmul step uses Ozaki; ``bmm`` and ``torch``
|
|
187
|
+
strategies fall back to kahan (fp64 promotion).
|
|
188
|
+
|
|
189
|
+
On Trainium (``HAS_NKI=True``): ``NotImplementedError`` preserved — the fused
|
|
190
|
+
NKI version requires trnblas Phase 2 double-double GEMM kernels (trnblas#22),
|
|
191
|
+
which hold both the main and correction PSUM tiles simultaneously in one NKI
|
|
192
|
+
program rather than dispatching four separate kernel calls.
|
|
193
|
+
|
|
194
|
+
Same named-mock pattern as ``_stochastic_round_cpu`` (SR, v0.11.0) and
|
|
195
|
+
``_mock_allreduce`` (reduce-parallel, v0.10.0).
|
|
196
|
+
|
|
197
|
+
### Notes
|
|
198
|
+
|
|
199
|
+
The remaining ``NotImplementedError`` for ``precision="dd"`` on Trainium gates
|
|
200
|
+
on trnblas#22. The CPU contract is now fully testable.
|
|
201
|
+
|
|
202
|
+
## [0.13.0] — 2026-04-22
|
|
203
|
+
|
|
204
|
+
### Fixed
|
|
205
|
+
|
|
206
|
+
- **`precision="sr"` now honored for the `bmm` strategy** — `_execute_bmm`
|
|
207
|
+
was calling ``nki_batched_matmul(A, B)`` without ``use_sr``, ignoring
|
|
208
|
+
``plan.precision``. The NKI kernel already supported ``use_sr`` since
|
|
209
|
+
v0.11.0; the dispatch layer just didn't thread it through.
|
|
210
|
+
|
|
211
|
+
### Added
|
|
212
|
+
|
|
213
|
+
- **`precision=` kwarg for `multi_einsum()`** — all contractions in a
|
|
214
|
+
``multi_einsum`` call now share the same precision mode. The homogeneous
|
|
215
|
+
batching path (``_try_batched_multi_einsum``) passes ``use_sr`` to
|
|
216
|
+
``nki_batched_matmul`` when ``precision="sr"``; ``"kahan"`` and ``"dd"``
|
|
217
|
+
fall through to the per-contraction loop which handles them correctly.
|
|
218
|
+
|
|
219
|
+
### Notes
|
|
220
|
+
|
|
221
|
+
``precision=`` is now uniformly honored across all dispatch paths: single
|
|
222
|
+
matmul (`einsum` → `_execute_matmul`), batched matmul (`einsum` →
|
|
223
|
+
`_execute_bmm`), path execution (`einsum` → `_execute_path` → recursive
|
|
224
|
+
`einsum`), and multi-contraction (`multi_einsum`).
|
|
225
|
+
|
|
226
|
+
## [0.12.0] — 2026-04-22
|
|
227
|
+
|
|
228
|
+
### Added
|
|
229
|
+
|
|
230
|
+
- **Mixed output-parallel + reduce-parallel sharding** — ``einsum()`` now
|
|
231
|
+
supports einsums where some ``ShardedTensor`` operands are partitioned along
|
|
232
|
+
an output dimension (output-parallel) and others along a contracted dimension
|
|
233
|
+
(reduce-parallel) in the same call.
|
|
234
|
+
|
|
235
|
+
The dispatch uses a nested loop: for each output shard ``s``, partial
|
|
236
|
+
contractions over all reduce shards are accumulated via
|
|
237
|
+
:func:`~trntensor.parallel._mock_allreduce` and the result becomes output
|
|
238
|
+
chunk ``s``. The return value is a ``ShardedTensor`` partitioned along the
|
|
239
|
+
output dimension.
|
|
240
|
+
|
|
241
|
+
Operands that are neither sharded but share the contracted index are
|
|
242
|
+
co-partitioned automatically (same behavior as pure reduce-parallel).
|
|
243
|
+
Output-parallel operand chunks are also co-partitioned along the contracted
|
|
244
|
+
index when they span it.
|
|
245
|
+
|
|
246
|
+
On Trainium (``HAS_NKI=True``) the gate is unchanged — the inner all-reduce
|
|
247
|
+
still requires ``nki.collectives`` (Neuron SDK 2.30+).
|
|
248
|
+
|
|
249
|
+
3-operand and higher chains work naturally: the inner recursive ``einsum()``
|
|
250
|
+
call receives dense operands and dispatches through the normal path.
|
|
251
|
+
|
|
252
|
+
### Notes
|
|
253
|
+
|
|
254
|
+
Mixed output-parallel + reduce-parallel with ``HAS_NKI=True`` raises
|
|
255
|
+
``NotImplementedError`` with the same ``nki.collectives`` message as pure
|
|
256
|
+
reduce-parallel. SDK 2.30+ unblocks both simultaneously.
|
|
257
|
+
|
|
258
|
+
## [0.11.0] — 2026-04-21
|
|
259
|
+
|
|
260
|
+
### Added
|
|
261
|
+
|
|
262
|
+
- **`precision="sr"` — stochastic rounding at the PSUM→SBUF boundary** —
|
|
263
|
+
adds a fourth precision mode to ``einsum()`` and ``plan_contraction()``.
|
|
264
|
+
|
|
265
|
+
On Trainium, ``matmul_kernel`` and ``batched_matmul_kernel`` replace the
|
|
266
|
+
``nisa.tensor_copy(psum → c_sbuf)`` downcast with
|
|
267
|
+
``nisa.activation(..., round_mode="stochastic")``. This rounds each FP32
|
|
268
|
+
PSUM element to its upper or lower BF16 neighbor with probability
|
|
269
|
+
proportional to the fractional distance — mean rounding error is zero
|
|
270
|
+
(Connolly–Higham–Mary, *SIAM J. Sci. Comput.*, 2021), replacing Wilkinson's
|
|
271
|
+
worst-case n·u bias with a √n·u bound.
|
|
272
|
+
|
|
273
|
+
On CPU (``HAS_NKI=False``), ``_stochastic_round_cpu`` applies the same
|
|
274
|
+
rounding to the ``torch.matmul`` output, enabling ``precision="sr"`` to be
|
|
275
|
+
tested in CPU-only CI. This mirrors the ``_mock_allreduce`` pattern from
|
|
276
|
+
v0.10.0: a named, documented stand-in that makes the hardware path testable
|
|
277
|
+
without hardware.
|
|
278
|
+
|
|
279
|
+
``"sr"`` applies only to the ``matmul`` strategy. For ``"bmm"``,
|
|
280
|
+
``"torch"``, and ``"path"`` strategies, ``precision="sr"`` is accepted
|
|
281
|
+
without error and uses fast (round-nearest) rounding.
|
|
282
|
+
|
|
283
|
+
**Correctness note**: for BF16 dot products with K ≥ ~300, stochastic
|
|
284
|
+
rounding is a *correctness requirement* for convergent Krylov iteration
|
|
285
|
+
(without SR, BF16 Krylov stagnates). Use ``precision="sr"`` when K is
|
|
286
|
+
large or accumulation bias matters.
|
|
287
|
+
|
|
288
|
+
### Notes
|
|
289
|
+
|
|
290
|
+
Mixed output-parallel + reduce-parallel operands in the same einsum remain
|
|
291
|
+
deferred to v0.12.0.
|
|
292
|
+
|
|
293
|
+
## [0.10.0] — 2026-04-21
|
|
294
|
+
|
|
295
|
+
### Added
|
|
296
|
+
|
|
297
|
+
- **Reduce-parallel sharding on CPU** — the ``NotImplementedError`` gate for
|
|
298
|
+
contracted-dimension sharding is now conditional on ``HAS_NKI``. On CPU
|
|
299
|
+
(``HAS_NKI=False``) reduce-parallel contractions dispatch through a mock
|
|
300
|
+
all-reduce (torch-based sum of per-shard partial results), making the full
|
|
301
|
+
sharding API testable in CI without hardware.
|
|
302
|
+
|
|
303
|
+
On Trainium (``HAS_NKI=True``) the gate is unchanged — ``nki.collectives``
|
|
304
|
+
is required for production reduce-parallel, arriving in Neuron SDK 2.30+.
|
|
305
|
+
|
|
306
|
+
- **Co-partitioning of plain-tensor operands** — when a reduce-parallel
|
|
307
|
+
``ShardedTensor`` operand partitions along a contracted index, ``einsum()``
|
|
308
|
+
automatically slices any non-sharded operand that shares that index along
|
|
309
|
+
the matching dimension per shard. No API change required; callers can mix
|
|
310
|
+
sharded and dense operands in the same reduce-parallel einsum.
|
|
311
|
+
|
|
312
|
+
- **``shard_boundaries(st)``** in ``trntensor.parallel`` — returns the
|
|
313
|
+
``(start, end)`` slice pairs for each shard. Used internally by the dispatch
|
|
314
|
+
layer; also useful for callers that need to manually co-partition ancillary
|
|
315
|
+
data structures.
|
|
316
|
+
|
|
317
|
+
- **``_mock_allreduce(partials)``** in ``trntensor.parallel`` — sums a list of
|
|
318
|
+
same-shape tensors element-wise. Named and documented to clearly identify the
|
|
319
|
+
operation that ``nki.collectives.allreduce`` will replace on hardware.
|
|
320
|
+
|
|
321
|
+
### Notes
|
|
322
|
+
|
|
323
|
+
Mixed output-parallel + reduce-parallel operands in the same einsum are not
|
|
324
|
+
yet supported and raise ``NotImplementedError``. This covers an edge case not
|
|
325
|
+
present in the DF-MP2 patterns; deferred to v0.11.0.
|
|
326
|
+
|
|
327
|
+
## [0.9.0] — 2026-04-18
|
|
328
|
+
|
|
329
|
+
### Added
|
|
330
|
+
|
|
331
|
+
- **`trntensor.parallel` module** — Phase 4 foundation for output-parallel tensor
|
|
332
|
+
contractions. Introduces ``ShardedTensor``, ``scatter``, and ``gather``:
|
|
333
|
+
- ``ShardedTensor``: wraps a list of dense chunk tensors split along a single
|
|
334
|
+
``partition_dim``. Carries the partition spec so ``einsum()`` can detect it
|
|
335
|
+
and classify the sharding mode.
|
|
336
|
+
- ``scatter(tensor, dim, n_shards)``: splits a dense tensor evenly along
|
|
337
|
+
``dim``; last shard absorbs any remainder.
|
|
338
|
+
- ``gather(st)``: reconstructs the dense tensor via ``torch.cat``.
|
|
339
|
+
|
|
340
|
+
- **Output-parallel sharding in ``einsum()``**: when any operand is a
|
|
341
|
+
``ShardedTensor``, ``einsum()`` checks whether the partition dimension maps to
|
|
342
|
+
an output index (output-parallel). If so, each shard's contraction is dispatched
|
|
343
|
+
independently (no cross-shard communication) and the result is returned as a
|
|
344
|
+
``ShardedTensor``. Works for all subscript patterns handled by the existing
|
|
345
|
+
planner (matmul, bmm, torch, path) and propagates through multi-operand chains.
|
|
346
|
+
|
|
347
|
+
- **Reduce-parallel gate**: if the partition dimension is a contraction index
|
|
348
|
+
(not in the output), ``einsum()`` raises ``NotImplementedError`` with a clear
|
|
349
|
+
explanation: reduce-parallel sharding requires ``nki.collectives`` all-reduce,
|
|
350
|
+
arriving in Neuron SDK 2.30+. The gate prevents silent wrong results.
|
|
351
|
+
|
|
352
|
+
### Notes
|
|
353
|
+
|
|
354
|
+
``nki.collectives`` (all-reduce, all-gather) is not available in NKI 0.3.0
|
|
355
|
+
Stable. Reduce-parallel sharding (contracted-dimension sharding) is gated until
|
|
356
|
+
SDK 2.30+. This sprint covers the output-parallel subset, which handles the
|
|
357
|
+
common row-parallel and column-parallel matmul patterns used in DF-MP2
|
|
358
|
+
AO→MO transform with large basis sets (nbasis > 3000 across chips).
|
|
359
|
+
|
|
360
|
+
## [0.8.0] — 2026-04-18
|
|
361
|
+
|
|
362
|
+
### Fixed
|
|
363
|
+
|
|
364
|
+
- **`_execute_path` now routes binary steps through `einsum()`** — multi-operand
|
|
365
|
+
contractions (3+ tensors via the greedy path planner) previously called
|
|
366
|
+
`torch.einsum` directly for each binary step, bypassing the entire trntensor
|
|
367
|
+
dispatch layer (plan cache, FLOP thresholds, NKI routing). The fix is a
|
|
368
|
+
one-line change: each step now calls `einsum(sub, a, b, precision=plan.precision)`,
|
|
369
|
+
so matmul-shaped steps dispatch to NKI when operand size clears the threshold.
|
|
370
|
+
All correctness tests are unaffected; top-level `ContractionPlan.backend` for
|
|
371
|
+
strategy `"path"` remains `"pytorch"` (accurate: no single NKI kernel spans
|
|
372
|
+
an arbitrary path). (#18 follow-up)
|
|
373
|
+
|
|
374
|
+
## [0.7.0] — 2026-04-17
|
|
375
|
+
|
|
376
|
+
### Added
|
|
377
|
+
|
|
378
|
+
- **N-tiled `ao_to_mo_transform_kernel`** — lifts `nbasis ≤ 512` and
|
|
379
|
+
`nvir ≤ 512` single-N-tile constraints. Step 1 now tiles the ν (basis)
|
|
380
|
+
dimension in ``TILE_N=512``-wide chunks; step 2 tiles the virtual-orbital
|
|
381
|
+
a dimension similarly. Enables full DF-MP2 AO→MO transform for large basis
|
|
382
|
+
sets: cc-pVTZ on naphthalene (nbasis≈572), aug-cc-pVTZ virtual spaces
|
|
383
|
+
(nvir > 512). Dispatcher pads both `nbasis` and `nvir` to ``TILE_N``
|
|
384
|
+
multiples (zero-fill); result sliced back to `(nocc, nvir, naux)`.
|
|
385
|
+
|
|
386
|
+
- **Simulator tests for N-tiled shapes** (`tests/test_nki_sim.py`,
|
|
387
|
+
`TestAoToMoTransformSimulator`) — three new cases: `test_n_tiled_nbasis`
|
|
388
|
+
(nbasis=640 > TILE_N), `test_n_tiled_nvir` (nvir=600 > TILE_N),
|
|
389
|
+
`test_both_n_tiled` (nbasis=640, nvir=600). Each verifies against the
|
|
390
|
+
CPU einsum reference.
|
|
391
|
+
|
|
392
|
+
### Changed
|
|
393
|
+
|
|
394
|
+
- **`ao_to_mo_transform` gates removed** — `NotImplementedError` for
|
|
395
|
+
`nbasis > 512` and `nvir > 512` removed; both constraints are now handled
|
|
396
|
+
by the tiled kernel + dispatcher. The `nocc > 128` gate remains (M-tiling
|
|
397
|
+
not yet implemented).
|
|
398
|
+
- **`_nki_ao_to_mo_transform` padding** — `nbasis` now padded to
|
|
399
|
+
`_round_up(nbasis, TILE_N)` instead of `_round_up(nbasis, TILE_K)`.
|
|
400
|
+
TILE_N alignment is stricter (multiples of 512 vs 128), but implies
|
|
401
|
+
TILE_K alignment (TILE_N = 4×TILE_K). `nvir` padding added.
|
|
402
|
+
|
|
403
|
+
## [0.6.0] — 2026-04-17
|
|
404
|
+
|
|
405
|
+
### Added
|
|
406
|
+
|
|
407
|
+
- **Tiled `mp2_energy_kernel`** — lifts `nvir ≤ 128` and `naux ≤ 128`
|
|
408
|
+
single-tile constraints. The kernel now M-tiles over the virtual-orbital
|
|
409
|
+
dimensions (TILE_M=128 per side) and K-tiles over the auxiliary index P
|
|
410
|
+
(TILE_K=128), enabling arbitrary `nvir` and `naux` (dispatcher pads to
|
|
411
|
+
tile multiples with zero-fill). Typical real-molecule sizes now supported:
|
|
412
|
+
aug-cc-pVDZ (naux≈300+), cc-pVTZ (nvir≈200+). Both `nvir=256` + `naux=256`
|
|
413
|
+
benchmarked at the same correctness tolerance as the single-tile path.
|
|
414
|
+
|
|
415
|
+
- **NVIR/NAUX padding in `_nki_mp2_energy` dispatch** — `_nki_mp2_energy`
|
|
416
|
+
now pads `B` to `(nocc, nvir_pad, naux_pad)` and `eps_vir` to
|
|
417
|
+
`(nvir_pad, 1)` before kernel entry. Zero-padding is safe: padded B
|
|
418
|
+
entries are 0, so tile contributions to `T*(2T-T.T)/Δ` are 0 regardless
|
|
419
|
+
of Δ.
|
|
420
|
+
|
|
421
|
+
- **Simulator tests for tiled shapes** (`tests/test_nki_sim.py`,
|
|
422
|
+
`TestMp2EnergySimulator`) — three new cases: `test_naux_tiled`
|
|
423
|
+
(nocc=4, nvir=32, naux=256), `test_nvir_tiled` (nocc=4, nvir=256,
|
|
424
|
+
naux=64), `test_both_tiled` (nocc=4, nvir=256, naux=256). Each verifies
|
|
425
|
+
against `_cpu_mp2_energy` via the NKI CPU simulator.
|
|
426
|
+
|
|
427
|
+
### Changed
|
|
428
|
+
|
|
429
|
+
- **`mp2_energy` gate removed** — the `NotImplementedError` for
|
|
430
|
+
`nvir > 128 or naux > 128` is gone. The NKI path now handles all sizes
|
|
431
|
+
≥ TILE_M / TILE_K via the tiled kernel; smaller sizes (padded up) are
|
|
432
|
+
handled identically to the original single-tile path.
|
|
433
|
+
|
|
434
|
+
## [0.5.0] — 2026-04-17
|
|
435
|
+
|
|
436
|
+
### Added
|
|
437
|
+
|
|
438
|
+
- **`multi_einsum` homogeneous batching** (#33 Phase 3) — when all contractions
|
|
439
|
+
share the same subscript, operand shapes, and resolve to a 2D matmul, they are
|
|
440
|
+
stacked and dispatched as a single `nki_batched_matmul` call instead of N
|
|
441
|
+
independent ones. Amortizes the ~0.67 ms fixed XLA dispatch overhead across the
|
|
442
|
+
batch (nocc²=4096 pair contractions: 2.7 s → 0.67 ms dispatch overhead). Falls
|
|
443
|
+
through to the per-contraction loop for heterogeneous sets.
|
|
444
|
+
|
|
445
|
+
- **`_MIN_NKI_FLOPS_PINNED` dispatch threshold** (#33) — second FLOP gate for
|
|
446
|
+
when operands are already XLA-resident (`to_xla` pre-applied). Profiler data
|
|
447
|
+
(trn1.2xlarge, `scripts/run_neuron_profile.sh --dispatch-timing`) shows the
|
|
448
|
+
NKI crossover drops from ~2 GFLOPs to ~900 MFLOPs when host→device transfer
|
|
449
|
+
is eliminated. Default: 1 GFLOPs. Override with `TRNTENSOR_MIN_NKI_FLOPS_PINNED`.
|
|
450
|
+
Dispatch automatically detects XLA-resident inputs and uses the lower threshold.
|
|
451
|
+
|
|
452
|
+
- **`docs/design/matmul_dispatch_findings.md`** — full per-step timing analysis
|
|
453
|
+
documenting XLA dispatch latency (~0.67 ms fixed overhead), transfer costs, and
|
|
454
|
+
the unpinned vs pre-pinned crossover. Raw JSON timing data included.
|
|
455
|
+
|
|
456
|
+
- **`docs/design/matmul_kernel_profile.md`** — Tensor Engine utilization profile
|
|
457
|
+
for `matmul_kernel` on trn1.2xlarge. Captures TE/VE split, DMA transfer
|
|
458
|
+
breakdown, and PSUM accumulation efficiency at medium (1024²) and large (2048²)
|
|
459
|
+
matrix sizes.
|
|
460
|
+
|
|
461
|
+
- **`infra/terraform/terraform.tfvars`** — VPC/subnet/region values for
|
|
462
|
+
`trntensor-ci-trn1` (us-east-1, vpc-cd49bfb0, subnet-1bd24d15).
|
|
463
|
+
|
|
464
|
+
### Changed
|
|
465
|
+
|
|
466
|
+
- **`infra/terraform/main.tf`** — default `aws_region` corrected from `us-west-2`
|
|
467
|
+
to `us-east-1` to match the existing VPC/subnet. Running `terraform apply`
|
|
468
|
+
without overrides now selects the correct region.
|
|
469
|
+
|
|
470
|
+
## [0.4.0] — 2026-04-16
|
|
471
|
+
|
|
472
|
+
### Added
|
|
473
|
+
|
|
474
|
+
- **`precision=` kwarg for `einsum` and `plan_contraction`** (#28 partial) —
|
|
475
|
+
three modes: `"fast"` (default, no change), `"kahan"` (promotes all operands
|
|
476
|
+
to `float64` before contracting via `torch.einsum`, casts result back to
|
|
477
|
+
original dtype — gives ~15.9 significant digits; bypasses NKI dispatch for
|
|
478
|
+
CPU compatibility), `"dd"` (raises `NotImplementedError` pending trnblas Phase
|
|
479
|
+
2 double-double GEMM). `precision` is included in the plan cache key so
|
|
480
|
+
`"fast"` and `"kahan"` plans cache independently. Useful for DF-MP2 / CCSD
|
|
481
|
+
energy convergence where fp32's ~7.2 digits are insufficient.
|
|
482
|
+
|
|
483
|
+
- **`dtype` mixed-precision override for `einsum`** (#22) — accepts string
|
|
484
|
+
aliases (`"bf16"`, `"fp16"`, `"f32"`) or `torch.dtype` instances. When set,
|
|
485
|
+
all operands are cast to the requested dtype before contracting and the
|
|
486
|
+
result is returned in that dtype. Matches Neuron SDK autocast recommendations;
|
|
487
|
+
use `dtype="bf16"` to route fp32 models through the NKI bf16 matmul path
|
|
488
|
+
without changing the model's weight dtype.
|
|
489
|
+
|
|
490
|
+
- **Neuron profiler script** (`scripts/run_neuron_profile.sh`) — captures a
|
|
491
|
+
Neuron Profiler 2.0 trace of `matmul_kernel` or `batched_matmul_kernel` via
|
|
492
|
+
SSM on the `trntensor-ci-trn1` instance. Supports `--probe` (API discovery),
|
|
493
|
+
`--kernel matmul|bmm`, and `--shape small|medium|large`. Adapted from the
|
|
494
|
+
trnblas profiler pattern (double-base64 encoding, auto start/stop).
|
|
495
|
+
|
|
496
|
+
- **Dispatch autotune script** (`scripts/autotune_dispatch.py`) (#33 partial)
|
|
497
|
+
— sweeps `(M, K, N)` shapes and measures NKI vs PyTorch wall-clock time to
|
|
498
|
+
find the empirical FLOP crossover on the current hardware. Reports the
|
|
499
|
+
recommended `TRNTENSOR_MIN_NKI_FLOPS` value; `--write-cache` persists the
|
|
500
|
+
result to `/var/tmp/trntensor-autotune/threshold.json`. The dispatch layer
|
|
501
|
+
reads this cache at startup (env var `TRNTENSOR_AUTOTUNE_CACHE` overrides
|
|
502
|
+
path; explicit `TRNTENSOR_MIN_NKI_FLOPS` always wins).
|
|
503
|
+
|
|
504
|
+
## [0.3.0] — 2026-04-16
|
|
505
|
+
|
|
506
|
+
### Added
|
|
507
|
+
|
|
508
|
+
- **Greedy contraction-path search for 3+ operand `einsum`** (#18) —
|
|
509
|
+
`plan_contraction()` now returns `strategy="path"` for three or more
|
|
510
|
+
operands. `_greedy_path_search` selects the cheapest binary contraction
|
|
511
|
+
order by minimizing per-step FLOP cost; the resulting
|
|
512
|
+
`ContractionPlan.contraction_path` drives `_execute_path`, which
|
|
513
|
+
routes each binary step through the full backend selection stack so
|
|
514
|
+
large sub-contractions still dispatch to NKI.
|
|
515
|
+
|
|
516
|
+
- **`multi_einsum` shared-operand XLA residency** (#19) — When NKI
|
|
517
|
+
dispatch is active, `multi_einsum` detects operand tensors that
|
|
518
|
+
appear in more than one contraction (by object identity) and
|
|
519
|
+
pre-pins them to the XLA device once before executing the loop.
|
|
520
|
+
Eliminates redundant host↔device transfers for workloads like DF-MP2
|
|
521
|
+
where the three-center integral tensor `B` feeds many pair
|
|
522
|
+
contractions. Falls back to the existing per-contraction loop on CPU.
|
|
523
|
+
|
|
524
|
+
- **Subscript and shape validation with descriptive errors** (#26) —
|
|
525
|
+
`plan_contraction()` now validates subscripts up-front and raises
|
|
526
|
+
`ValueError` with precise messages: wrong operand count, rank
|
|
527
|
+
mismatch, and inconsistent index sizes are all caught before any
|
|
528
|
+
torch operation runs. Eliminates cryptic downstream errors from
|
|
529
|
+
`torch.einsum`.
|
|
530
|
+
|
|
531
|
+
- **PEP 561 `py.typed` marker** (#25) — `trntensor` now ships a
|
|
532
|
+
`py.typed` file so type checkers (mypy, pyright, etc.) recognise
|
|
533
|
+
the package as typed and apply inline annotations.
|
|
534
|
+
|
|
535
|
+
- **`alpha`/`beta` scaling for `einsum`** (#20) — matches cuTENSOR's
|
|
536
|
+
GEMM-style interface:
|
|
537
|
+
`einsum(subscripts, A, B, alpha=α, beta=β, out=C)` returns
|
|
538
|
+
`α * contract(A, B) + β * C`. Defaults (`alpha=1, beta=0, out=None`)
|
|
539
|
+
preserve existing behaviour exactly. Useful for accumulation patterns
|
|
540
|
+
and in-place gradient updates without an extra allocation.
|
|
541
|
+
|
|
542
|
+
- **Contraction plan cache** (#29 partial) — `plan_contraction()` caches
|
|
543
|
+
results by `(subscripts, operand shapes)`. Repeated calls with the same
|
|
544
|
+
subscript and shapes skip replanning entirely. `clear_plan_cache()` and
|
|
545
|
+
`plan_cache_info()` are exported from the top-level API.
|
|
546
|
+
|
|
547
|
+
- **Tensor Train (TT) decomposition** (#23) — `tt_decompose(tensor, max_rank)`
|
|
548
|
+
decomposes a d-dimensional tensor into a chain of 3-tensor cores via TT-SVD
|
|
549
|
+
(Oseledets 2011), bond dimension capped at `max_rank`. `tt_reconstruct(cores)`
|
|
550
|
+
contracts the chain back. Useful for DMRG-style high-dimensional compression.
|
|
551
|
+
|
|
552
|
+
- **Non-negative CP and warm-start CP** (#24) — `cp_decompose` gains two new
|
|
553
|
+
keyword arguments: `nonneg=True` switches ALS to multiplicative updates
|
|
554
|
+
to enforce non-negative factors; `factors=` accepts a list of pre-computed
|
|
555
|
+
factor matrices to warm-start from, skipping random initialization.
|
|
556
|
+
Both options compose.
|
|
557
|
+
|
|
558
|
+
## [0.2.0] — 2026-04-15
|
|
559
|
+
|
|
560
|
+
### Added
|
|
561
|
+
|
|
562
|
+
- **`trntensor.to_xla(tensor)` / `trntensor.from_xla(tensor)`** — explicit
|
|
563
|
+
operand residency on the Trainium XLA device. Pre-pinning operands
|
|
564
|
+
lets repeated trntensor calls skip per-dispatch host↔device
|
|
565
|
+
transfer, which otherwise dominates at current kernel sizes. The
|
|
566
|
+
full DF-MP2 pipeline (`ao_to_mo_transform` → `mp2_energy`) with all
|
|
567
|
+
operands pre-pinned pays transfer cost once instead of once per
|
|
568
|
+
call. The dispatch layer's `_to_xla` helper takes a fast path when
|
|
569
|
+
every operand is already on XLA, returning the result on XLA — the
|
|
570
|
+
caller decides when to pull back via `from_xla`. Closes #34.
|
|
571
|
+
- **`trntensor.ao_to_mo_transform(eri, C_occ, C_vir)`** — fused 4-index
|
|
572
|
+
AO→MO integral transform with K-tiling over the basis index (#37).
|
|
573
|
+
One NKI program computes `B[i,a,P] = Σ_{μν} C_occ[μ,i] · C_vir[ν,a] ·
|
|
574
|
+
eri[μ,ν,P]`. Tiles over μ (step 1) and ν (step 2) in TILE_K=128
|
|
575
|
+
chunks so `nbasis` up to 512 is supported; dispatch pads to the
|
|
576
|
+
nearest TILE_K multiple. Shape constraints: `nbasis ≤ 512`,
|
|
577
|
+
`nocc ≤ 128`, `nvir ≤ 512`. Composes with `mp2_energy` for the full
|
|
578
|
+
DF-MP2 pipeline from AO integrals to correlation energy. Validated
|
|
579
|
+
on trn1 (hardware) and via the CPU simulator CI job.
|
|
580
|
+
- **NKI CPU simulator dispatch** via `TRNTENSOR_USE_SIMULATOR=1`.
|
|
581
|
+
Routes kernels through `nki.simulate(kernel)(numpy_args)` on CPU,
|
|
582
|
+
bypassing `torch_xla` + NEFF compile. Iteration loop drops from
|
|
583
|
+
~5 min per SSM round-trip to seconds. Correctness-only — MLIR
|
|
584
|
+
verifier errors remain hardware-only.
|
|
585
|
+
- **`nki-simulator` CI job on `ubuntu-latest`** — runs the
|
|
586
|
+
`nki_simulator`-marked suite against `nki>=0.3.0` from the AWS pip
|
|
587
|
+
index on every push + PR. Zero AWS cost for the correctness gate.
|
|
588
|
+
- `tests/test_nki_sim.py` — simulator-backed correctness suite,
|
|
589
|
+
marker `nki_simulator`. Covers matmul, batched matmul,
|
|
590
|
+
`ao_to_mo_transform` (including K-tiled nbasis=256 and non-aligned
|
|
591
|
+
nbasis=200), and `mp2_energy`.
|
|
592
|
+
- `scripts/run_simulator_tests.sh` — SSM runner for the simulator
|
|
593
|
+
suite on the trn1 DLAMI.
|
|
594
|
+
- `docs/developing_kernels.md` — NKI kernel development guide with
|
|
595
|
+
trntensor-specific env vars and file locations.
|
|
596
|
+
|
|
597
|
+
### Changed
|
|
598
|
+
|
|
599
|
+
- **Migrated to NKI 0.3.0 / Neuron SDK 2.29.** Canonical `nki.*`
|
|
600
|
+
namespace; the legacy `neuronxcc.nki.*` shim is no longer used.
|
|
601
|
+
Kernels updated for the NKI 0.3.0 breaking-change surface:
|
|
602
|
+
`nisa.nc_matmul(dst=, stationary=, moving=, accumulate=True)` (all
|
|
603
|
+
kwargs); `nl.copy(psum)` returns a view — use `nl.ndarray` +
|
|
604
|
+
`nisa.tensor_copy` instead; tensor-tensor `nl.divide` dropped — use
|
|
605
|
+
`multiply × reciprocal`.
|
|
606
|
+
- Dev workflow migrated to [uv](https://github.com/astral-sh/uv).
|
|
607
|
+
`uv sync --extra dev` replaces `pip install -e ".[dev]"`; CI uses
|
|
608
|
+
`astral-sh/setup-uv@v6` and `uv run pytest` / `uvx ruff`. `uv.lock`
|
|
609
|
+
is committed for reproducible installs.
|
|
610
|
+
- Removed the `[neuron]` optional-dependencies extra. `nki` is
|
|
611
|
+
installed from the AWS Neuron pip index in CI or provided by the
|
|
612
|
+
Deep Learning AMI's pre-built venv on hardware.
|
|
613
|
+
- `CONTRIBUTING.md` updated to reflect the uv-based setup.
|
|
614
|
+
|
|
615
|
+
### Fixed
|
|
616
|
+
|
|
617
|
+
- `mp2_energy_kernel` 1D-load ambiguity on pre-pinned XLA ε inputs
|
|
618
|
+
(#38). Reshape `eps_occ` / `eps_vir` to 2D `(N, 1)` at the dispatch
|
|
619
|
+
boundary; partition-dim inference is unambiguous regardless of
|
|
620
|
+
residency state.
|
|
621
|
+
- `mp2_energy_kernel` 0-D SBUF rejection (`SBUF tensors must have at
|
|
622
|
+
least 2 dimensions`). Per-`(i,j)` reduction now uses a persistent
|
|
623
|
+
`(1, 1)` SBUF accumulator (`nl.zeros((1, 1), ...)`) instead of a
|
|
624
|
+
direct `nl.sum` store.
|
|
625
|
+
- `_to_xla` fast-path now calls `xm.mark_step()` when operands are
|
|
626
|
+
already on XLA, forcing pending lazy computations to materialize
|
|
627
|
+
before the next kernel dispatch.
|
|
628
|
+
|
|
629
|
+
### Known limitation
|
|
630
|
+
|
|
631
|
+
- The full DF-MP2 pipeline (`ao_to_mo_transform` → `mp2_energy`) with
|
|
632
|
+
every operand pre-pinned exposes an NKI compiler bug on trn1: the
|
|
633
|
+
combined XLA lazy graph provokes `trn2-only shared memory`
|
|
634
|
+
instructions that fail verification on trn1. Workaround: `from_xla`
|
|
635
|
+
the intermediate `B` between the two calls. Tracked in #39 for
|
|
636
|
+
upstream AWS escalation.
|
|
637
|
+
|
|
638
|
+
## [0.1.2] — 2026-04-12
|
|
639
|
+
|
|
640
|
+
### Changed
|
|
641
|
+
|
|
642
|
+
- `set_backend("nki")` now raises `RuntimeError` on non-Neuron hosts
|
|
643
|
+
instead of silently accepting the backend and failing later. Matches
|
|
644
|
+
the sibling-suite pattern.
|
|
645
|
+
- CI actions bumped to `actions/checkout@v6` + `actions/setup-python@v6`
|
|
646
|
+
(Node.js 24), ahead of GitHub's June 2026 default switch.
|
|
647
|
+
- pyproject metadata normalized across the trnsci suite (author email,
|
|
648
|
+
URLs, classifier list).
|
|
649
|
+
- Standalone `docs.yml` removed — docs are now served via `trnsci.dev`
|
|
650
|
+
through the umbrella's combined build. `notify-umbrella.yml` pings
|
|
651
|
+
the umbrella on docs changes.
|
|
652
|
+
- `infra/terraform/main.tf`: user-data clone URL corrected to
|
|
653
|
+
`trnsci/trntensor`.
|
|
654
|
+
|
|
655
|
+
### Added
|
|
656
|
+
|
|
657
|
+
- `benchmarks/bench_einsum.py` — pytest-benchmark cases for einsum
|
|
658
|
+
dispatch and decompositions. CPU baseline numbers populated in
|
|
659
|
+
`docs/benchmarks.md`.
|
|
660
|
+
- `tests/test_nki.py` — backend-dispatch unit tests (CPU path).
|
|
661
|
+
|
|
662
|
+
## [0.1.1] — 2026-04-12
|
|
663
|
+
|
|
664
|
+
### Added
|
|
665
|
+
|
|
666
|
+
- mkdocs site with `index`, `installation`, `quickstart`, `api`, `architecture`, `aws_setup`
|
|
667
|
+
- `infra/terraform/` for on-hardware CI instance provisioning
|
|
668
|
+
- `scripts/run_neuron_tests.sh` and benchmark helpers
|
|
669
|
+
- GitHub Actions `ci.yml`, `docs.yml`, `publish.yml`
|
|
670
|
+
- `Issues` and `Documentation` URLs in pyproject.toml
|
|
671
|
+
- `tests/test_plan.py` — dedicated planner unit tests (parsing,
|
|
672
|
+
strategy selection, FLOP estimates); extended CP / Tucker coverage
|
|
673
|
+
(all-zero tensor, rank > min dim, unequal mode ranks)
|
|
674
|
+
|
|
675
|
+
### Changed
|
|
676
|
+
|
|
677
|
+
- Bumped `neuronxcc` floor from `>=2.15` to `>=2.24` to unify with the
|
|
678
|
+
rest of the trnsci suite. `torch-neuronx` floor bumped to `>=2.9`.
|
|
679
|
+
|
|
680
|
+
## [0.1.0] — 2026-04-12
|
|
681
|
+
|
|
682
|
+
### Added
|
|
683
|
+
|
|
684
|
+
- Initial scaffold: einsum with contraction planning, CP / Tucker decompositions
|
|
685
|
+
- NKI dispatch with fused-contraction kernel stubs
|
|
686
|
+
- `examples/df_mp2_einsum.py` — DF-MP2 energy via einsum
|