trnblas 0.2.0__py3-none-any.whl

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.
trnblas/__init__.py ADDED
@@ -0,0 +1,35 @@
1
+ """
2
+ trnblas — BLAS operations for AWS Trainium via NKI.
3
+
4
+ Provides Level 1 (vector), Level 2 (matrix-vector), and Level 3 (matrix-matrix)
5
+ BLAS operations with NKI kernel acceleration on Trainium hardware.
6
+ Part of the trn-* scientific computing suite by Playground Logic.
7
+
8
+ Target workloads: DF-MP2 tensor contractions, Fock matrix builds,
9
+ Cholesky-based density fitting, and general scientific linear algebra.
10
+ """
11
+
12
+ __version__ = "0.2.0"
13
+
14
+ # Level 1 — Vector operations
15
+ from .level1 import axpy, dot, nrm2, scal, asum, iamax
16
+
17
+ # Level 2 — Matrix-vector operations
18
+ from .level2 import gemv, symv, trmv, ger
19
+
20
+ # Level 3 — Matrix-matrix operations
21
+ from .level3 import gemm, batched_gemm, symm, syrk, trsm, trmm
22
+
23
+ # Backend control
24
+ from .nki import HAS_NKI, set_backend, get_backend
25
+
26
+ __all__ = [
27
+ # Level 1
28
+ "axpy", "dot", "nrm2", "scal", "asum", "iamax",
29
+ # Level 2
30
+ "gemv", "symv", "trmv", "ger",
31
+ # Level 3
32
+ "gemm", "batched_gemm", "symm", "syrk", "trsm", "trmm",
33
+ # Backend
34
+ "HAS_NKI", "set_backend", "get_backend",
35
+ ]
trnblas/level1.py ADDED
@@ -0,0 +1,45 @@
1
+ """
2
+ BLAS Level 1 — Vector operations.
3
+
4
+ axpy, dot, nrm2, scal, asum, iamax
5
+ All operate on torch tensors with NKI dispatch for Trainium acceleration.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import math
11
+ import torch
12
+ from typing import Optional
13
+
14
+
15
+ def axpy(alpha: float, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
16
+ """y = alpha * x + y"""
17
+ return alpha * x + y
18
+
19
+
20
+ def dot(x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
21
+ """Dot product: x^T y
22
+
23
+ Returns scalar tensor.
24
+ """
25
+ return torch.dot(x.reshape(-1), y.reshape(-1))
26
+
27
+
28
+ def nrm2(x: torch.Tensor) -> torch.Tensor:
29
+ """Euclidean norm: ||x||_2"""
30
+ return torch.linalg.norm(x.reshape(-1))
31
+
32
+
33
+ def scal(alpha: float, x: torch.Tensor) -> torch.Tensor:
34
+ """x = alpha * x"""
35
+ return alpha * x
36
+
37
+
38
+ def asum(x: torch.Tensor) -> torch.Tensor:
39
+ """Sum of absolute values: sum(|x_i|)"""
40
+ return torch.abs(x).sum()
41
+
42
+
43
+ def iamax(x: torch.Tensor) -> int:
44
+ """Index of element with maximum absolute value."""
45
+ return torch.argmax(torch.abs(x.reshape(-1))).item()
trnblas/level2.py ADDED
@@ -0,0 +1,86 @@
1
+ """
2
+ BLAS Level 2 — Matrix-vector operations.
3
+
4
+ gemv, symv, trmv, ger
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import torch
10
+ from typing import Optional
11
+
12
+
13
+ def gemv(
14
+ alpha: float,
15
+ A: torch.Tensor,
16
+ x: torch.Tensor,
17
+ beta: float = 0.0,
18
+ y: Optional[torch.Tensor] = None,
19
+ trans: bool = False,
20
+ ) -> torch.Tensor:
21
+ """General matrix-vector multiply: y = alpha * op(A) * x + beta * y
22
+
23
+ op(A) = A if trans=False, A^T if trans=True.
24
+ """
25
+ mat = A.T if trans else A
26
+ result = alpha * torch.mv(mat, x)
27
+ if y is not None and beta != 0.0:
28
+ result = result + beta * y
29
+ return result
30
+
31
+
32
+ def symv(
33
+ alpha: float,
34
+ A: torch.Tensor,
35
+ x: torch.Tensor,
36
+ beta: float = 0.0,
37
+ y: Optional[torch.Tensor] = None,
38
+ uplo: str = "upper",
39
+ ) -> torch.Tensor:
40
+ """Symmetric matrix-vector multiply: y = alpha * A * x + beta * y
41
+
42
+ A is symmetric; only the upper or lower triangle is referenced.
43
+ """
44
+ if uplo == "upper":
45
+ sym = torch.triu(A) + torch.triu(A, diagonal=1).T
46
+ else:
47
+ sym = torch.tril(A) + torch.tril(A, diagonal=-1).T
48
+ result = alpha * torch.mv(sym, x)
49
+ if y is not None and beta != 0.0:
50
+ result = result + beta * y
51
+ return result
52
+
53
+
54
+ def trmv(
55
+ A: torch.Tensor,
56
+ x: torch.Tensor,
57
+ uplo: str = "upper",
58
+ trans: bool = False,
59
+ diag: str = "nonunit",
60
+ ) -> torch.Tensor:
61
+ """Triangular matrix-vector multiply: x = op(A) * x
62
+
63
+ uplo: 'upper' or 'lower'
64
+ diag: 'unit' or 'nonunit'
65
+ """
66
+ if uplo == "upper":
67
+ tri = torch.triu(A)
68
+ else:
69
+ tri = torch.tril(A)
70
+ if diag == "unit":
71
+ tri = tri - torch.diag(torch.diag(tri)) + torch.eye(A.shape[0], dtype=A.dtype, device=A.device)
72
+ mat = tri.T if trans else tri
73
+ return torch.mv(mat, x)
74
+
75
+
76
+ def ger(
77
+ alpha: float,
78
+ x: torch.Tensor,
79
+ y: torch.Tensor,
80
+ A: Optional[torch.Tensor] = None,
81
+ ) -> torch.Tensor:
82
+ """Rank-1 update: A = alpha * x * y^T + A"""
83
+ result = alpha * torch.outer(x, y)
84
+ if A is not None:
85
+ result = result + A
86
+ return result
trnblas/level3.py ADDED
@@ -0,0 +1,203 @@
1
+ """
2
+ BLAS Level 3 — Matrix-matrix operations.
3
+
4
+ gemm, symm, syrk, trsm, trmm
5
+
6
+ These are the critical path for scientific computing on Trainium:
7
+ - DF-MP2 tensor contractions → batched GEMM
8
+ - Fock matrix build → SYMM
9
+ - Cholesky-based density fitting → TRSM
10
+ - Metric contraction J^{-1/2} → SYRK
11
+
12
+ NKI dispatch for GEMM provides stationary tile reuse on the Tensor Engine.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import torch
18
+ from typing import Optional
19
+
20
+ from .nki import get_backend, HAS_NKI
21
+
22
+
23
+ def gemm(
24
+ alpha: float,
25
+ A: torch.Tensor,
26
+ B: torch.Tensor,
27
+ beta: float = 0.0,
28
+ C: Optional[torch.Tensor] = None,
29
+ transA: bool = False,
30
+ transB: bool = False,
31
+ ) -> torch.Tensor:
32
+ """General matrix multiply: C = alpha * op(A) @ op(B) + beta * C
33
+
34
+ op(X) = X if trans=False, X^T if trans=True.
35
+
36
+ This is the workhorse for DF-MP2:
37
+ (ia|P) = Σ_μν C_μi @ (μν|P) @ C_νa → two GEMMs per aux index
38
+ B_ia^P = (ia|Q) @ J^{-1/2}_{QP} → one GEMM
39
+ E_MP2 = Σ B_ia^P @ B_jb^P → batched GEMM
40
+
41
+ On Trainium, dispatches to NKI GEMM with stationary tile reuse.
42
+ """
43
+ from .nki.dispatch import nki_gemm, _use_nki
44
+
45
+ a = A.T if transA else A
46
+ b = B.T if transB else B
47
+
48
+ if _use_nki() and a.dim() == 2 and b.dim() == 2:
49
+ result = alpha * nki_gemm(a, b)
50
+ else:
51
+ result = alpha * torch.matmul(a, b)
52
+
53
+ if C is not None and beta != 0.0:
54
+ result = result + beta * C
55
+
56
+ return result
57
+
58
+
59
+ def batched_gemm(
60
+ alpha: float,
61
+ A: torch.Tensor,
62
+ B: torch.Tensor,
63
+ beta: float = 0.0,
64
+ C: Optional[torch.Tensor] = None,
65
+ transA: bool = False,
66
+ transB: bool = False,
67
+ ) -> torch.Tensor:
68
+ """Batched GEMM: C[i] = alpha * op(A[i]) @ op(B[i]) + beta * C[i]
69
+
70
+ A, B have shape (batch, M, K) and (batch, K, N) respectively.
71
+
72
+ Critical for DF-MP2 energy evaluation where contractions are
73
+ independent across auxiliary basis indices.
74
+ """
75
+ a = A.transpose(-2, -1) if transA else A
76
+ b = B.transpose(-2, -1) if transB else B
77
+ result = alpha * torch.bmm(a, b)
78
+ if C is not None and beta != 0.0:
79
+ result = result + beta * C
80
+ return result
81
+
82
+
83
+ def symm(
84
+ alpha: float,
85
+ A: torch.Tensor,
86
+ B: torch.Tensor,
87
+ beta: float = 0.0,
88
+ C: Optional[torch.Tensor] = None,
89
+ side: str = "left",
90
+ uplo: str = "upper",
91
+ ) -> torch.Tensor:
92
+ """Symmetric matrix multiply: C = alpha * A @ B + beta * C (side='left')
93
+ or C = alpha * B @ A + beta * C (side='right')
94
+
95
+ A is symmetric; only upper or lower triangle referenced.
96
+ Used in Fock matrix construction: F = H_core + J - K
97
+ where J and K involve symmetric density matrix contractions.
98
+ """
99
+ if uplo == "upper":
100
+ sym = torch.triu(A) + torch.triu(A, diagonal=1).T
101
+ else:
102
+ sym = torch.tril(A) + torch.tril(A, diagonal=-1).T
103
+
104
+ if side == "left":
105
+ result = alpha * torch.matmul(sym, B)
106
+ else:
107
+ result = alpha * torch.matmul(B, sym)
108
+
109
+ if C is not None and beta != 0.0:
110
+ result = result + beta * C
111
+ return result
112
+
113
+
114
+ def syrk(
115
+ alpha: float,
116
+ A: torch.Tensor,
117
+ beta: float = 0.0,
118
+ C: Optional[torch.Tensor] = None,
119
+ trans: bool = False,
120
+ uplo: str = "upper",
121
+ ) -> torch.Tensor:
122
+ """Symmetric rank-k update: C = alpha * A @ A^T + beta * C (trans=False)
123
+ or C = alpha * A^T @ A + beta * C (trans=True)
124
+
125
+ Used in metric contraction for density fitting:
126
+ J_{PQ} = Σ_μν (P|μν)(μν|Q) which is A^T @ A form.
127
+ """
128
+ if trans:
129
+ result = alpha * torch.matmul(A.T, A)
130
+ else:
131
+ result = alpha * torch.matmul(A, A.T)
132
+
133
+ if C is not None and beta != 0.0:
134
+ result = result + beta * C
135
+
136
+ # Symmetrize (numerical stability)
137
+ result = 0.5 * (result + result.T)
138
+ return result
139
+
140
+
141
+ def trsm(
142
+ alpha: float,
143
+ A: torch.Tensor,
144
+ B: torch.Tensor,
145
+ side: str = "left",
146
+ uplo: str = "upper",
147
+ trans: bool = False,
148
+ diag: str = "nonunit",
149
+ ) -> torch.Tensor:
150
+ """Triangular solve with multiple RHS: op(A) @ X = alpha * B (side='left')
151
+ or X @ op(A) = alpha * B (side='right')
152
+
153
+ Returns X.
154
+
155
+ Critical for Cholesky-based density fitting:
156
+ Given J = L @ L^T, solve L @ X = (μν|P) for X,
157
+ then B_ia^P = C^T @ X gives the DF coefficients.
158
+ """
159
+ if uplo == "upper":
160
+ tri = torch.triu(A)
161
+ else:
162
+ tri = torch.tril(A)
163
+
164
+ if diag == "unit":
165
+ tri = tri - torch.diag(torch.diag(tri)) + torch.eye(A.shape[0], dtype=A.dtype, device=A.device)
166
+
167
+ mat = tri.T if trans else tri
168
+
169
+ if side == "left":
170
+ # Solve mat @ X = alpha * B
171
+ return alpha * torch.linalg.solve_triangular(mat, B, upper=(uplo == "upper" and not trans) or (uplo == "lower" and trans))
172
+ else:
173
+ # Solve X @ mat = alpha * B → mat^T @ X^T = alpha * B^T
174
+ upper_flag = (uplo == "lower" and not trans) or (uplo == "upper" and trans)
175
+ return alpha * torch.linalg.solve_triangular(mat.T, B.T, upper=upper_flag).T
176
+
177
+
178
+ def trmm(
179
+ alpha: float,
180
+ A: torch.Tensor,
181
+ B: torch.Tensor,
182
+ side: str = "left",
183
+ uplo: str = "upper",
184
+ trans: bool = False,
185
+ diag: str = "nonunit",
186
+ ) -> torch.Tensor:
187
+ """Triangular matrix multiply: B = alpha * op(A) @ B (side='left')
188
+ or B = alpha * B @ op(A) (side='right')
189
+ """
190
+ if uplo == "upper":
191
+ tri = torch.triu(A)
192
+ else:
193
+ tri = torch.tril(A)
194
+
195
+ if diag == "unit":
196
+ tri = tri - torch.diag(torch.diag(tri)) + torch.eye(A.shape[0], dtype=A.dtype, device=A.device)
197
+
198
+ mat = tri.T if trans else tri
199
+
200
+ if side == "left":
201
+ return alpha * torch.matmul(mat, B)
202
+ else:
203
+ return alpha * torch.matmul(B, mat)
@@ -0,0 +1,5 @@
1
+ """NKI kernel dispatch for Trainium BLAS acceleration."""
2
+
3
+ from .dispatch import HAS_NKI, set_backend, get_backend, nki_gemm
4
+
5
+ __all__ = ["HAS_NKI", "set_backend", "get_backend", "nki_gemm"]
@@ -0,0 +1,121 @@
1
+ """
2
+ NKI dispatch for BLAS operations.
3
+
4
+ Backend selection mirrors trnfft: auto/pytorch/nki.
5
+ The GEMM kernel is the primary acceleration target — it uses stationary
6
+ tile reuse on the Tensor Engine for 2x fewer SBUF loads vs naive.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import torch
12
+
13
+ try:
14
+ import neuronxcc.nki as nki
15
+ import neuronxcc.nki.language as nl
16
+ import neuronxcc.nki.isa as nisa
17
+ HAS_NKI = True
18
+ except ImportError:
19
+ HAS_NKI = False
20
+
21
+ _backend = "auto"
22
+
23
+
24
+ def set_backend(backend: str):
25
+ global _backend
26
+ assert backend in ("auto", "pytorch", "nki")
27
+ if backend == "nki" and not HAS_NKI:
28
+ raise RuntimeError("NKI backend requires neuronxcc")
29
+ _backend = backend
30
+
31
+
32
+ def get_backend() -> str:
33
+ return _backend
34
+
35
+
36
+ def _use_nki() -> bool:
37
+ if _backend == "nki":
38
+ return True
39
+ if _backend == "pytorch":
40
+ return False
41
+ return HAS_NKI
42
+
43
+
44
+ def nki_gemm(A: torch.Tensor, B: torch.Tensor) -> torch.Tensor:
45
+ """GEMM with NKI dispatch.
46
+
47
+ On NKI backend: uses tiled GEMM with stationary A reuse.
48
+ On PyTorch backend: torch.matmul.
49
+
50
+ NKI GEMM strategy (stationary tile reuse):
51
+ 1. Load A tile to SBUF as stationary (stays in systolic array)
52
+ 2. Stream B tiles as moving → accumulate in PSUM
53
+ 3. One A load serves multiple B tiles
54
+
55
+ For DF-MP2 tensor contractions where A is the MO coefficient matrix
56
+ (reused across auxiliary basis indices), this cuts SBUF loads in half.
57
+ """
58
+ if _use_nki():
59
+ return _nki_gemm_impl(A, B)
60
+ return torch.matmul(A, B)
61
+
62
+
63
+ def _nki_gemm_impl(A: torch.Tensor, B: torch.Tensor) -> torch.Tensor:
64
+ """NKI GEMM implementation.
65
+
66
+ TODO: Wire to actual NKI kernel with tiling once validated on trn1/trn2.
67
+ The kernel should:
68
+ - Tile A into 128×128 blocks (SBUF capacity)
69
+ - For each A tile, stream all corresponding B tiles through the systolic array
70
+ - Accumulate partial products in PSUM
71
+ - Handle edge tiles for non-128-aligned dimensions
72
+
73
+ See neuron-complex-ops kernels_optimized.py for the complex variant
74
+ of this pattern — real GEMM is simpler (no real/imag split needed).
75
+ """
76
+ if not HAS_NKI:
77
+ raise RuntimeError("NKI not available")
78
+ # Fallback until kernel is validated on hardware
79
+ return torch.matmul(A, B)
80
+
81
+
82
+ if HAS_NKI:
83
+
84
+ @nki.jit
85
+ def gemm_kernel(A_ref, B_ref, C_ref, M: int, N: int, K: int):
86
+ """Tiled GEMM kernel for Trainium NeuronCore.
87
+
88
+ C[M,N] = A[M,K] @ B[K,N]
89
+
90
+ Tiling: 128×128 tiles for SBUF, accumulate in PSUM.
91
+ A tiles are stationary (loaded once, reused across N tiles).
92
+ B tiles are streamed (moving operand in systolic array).
93
+
94
+ STUB: Scaffolded for on-hardware validation.
95
+ """
96
+ TILE = 128
97
+
98
+ for m_tile in nl.affine_range(M // TILE):
99
+ for k_tile in nl.affine_range(K // TILE):
100
+ # Load A tile — stationary in systolic array
101
+ a_tile = nl.load(
102
+ A_ref[m_tile * TILE:(m_tile + 1) * TILE,
103
+ k_tile * TILE:(k_tile + 1) * TILE]
104
+ )
105
+
106
+ for n_tile in nl.affine_range(N // TILE):
107
+ # Stream B tile — moving operand
108
+ b_tile = nl.load(
109
+ B_ref[k_tile * TILE:(k_tile + 1) * TILE,
110
+ n_tile * TILE:(n_tile + 1) * TILE]
111
+ )
112
+
113
+ # Matmul → accumulate in PSUM
114
+ c_partial = nisa.nc_matmul(a_tile, b_tile)
115
+
116
+ # Store (would accumulate across k_tiles in practice)
117
+ nl.store(
118
+ C_ref[m_tile * TILE:(m_tile + 1) * TILE,
119
+ n_tile * TILE:(n_tile + 1) * TILE],
120
+ c_partial
121
+ )
@@ -0,0 +1,139 @@
1
+ Metadata-Version: 2.4
2
+ Name: trnblas
3
+ Version: 0.2.0
4
+ Summary: BLAS operations for AWS Trainium via NKI
5
+ Author-email: Scott Friedman <scott@playgroundlogic.co>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/scttfrdmn/trnblas
8
+ Project-URL: Repository, https://github.com/scttfrdmn/trnblas
9
+ Project-URL: Issues, https://github.com/scttfrdmn/trnblas/issues
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Scientific/Engineering
14
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: torch>=2.1
19
+ Requires-Dist: numpy>=1.24
20
+ Provides-Extra: neuron
21
+ Requires-Dist: neuronxcc>=2.15; extra == "neuron"
22
+ Requires-Dist: torch-neuronx>=2.1; extra == "neuron"
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=7.0; extra == "dev"
25
+ Requires-Dist: pytest-benchmark>=4.0; extra == "dev"
26
+ Requires-Dist: scipy>=1.11; extra == "dev"
27
+ Dynamic: license-file
28
+
29
+ # trnblas
30
+
31
+ [![CI](https://github.com/scttfrdmn/trnblas/actions/workflows/ci.yml/badge.svg)](https://github.com/scttfrdmn/trnblas/actions/workflows/ci.yml)
32
+ [![PyPI](https://img.shields.io/pypi/v/trnblas)](https://pypi.org/project/trnblas/)
33
+ [![Python](https://img.shields.io/pypi/pyversions/trnblas)](https://pypi.org/project/trnblas/)
34
+ [![License](https://img.shields.io/github/license/scttfrdmn/trnblas)](LICENSE)
35
+ [![Docs](https://img.shields.io/badge/docs-mkdocs-blue)](https://scttfrdmn.github.io/trnblas/)
36
+
37
+ BLAS operations for AWS Trainium via NKI (Neuron Kernel Interface).
38
+
39
+ Trainium ships no BLAS library. `trnblas` provides Level 1-3 BLAS operations with NKI kernel acceleration on the Tensor Engine, targeting scientific computing workloads that are GEMM-dominated.
40
+
41
+ Part of the **trn-\*** scientific computing suite by [Playground Logic](https://playgroundlogic.co).
42
+
43
+ ## Why
44
+
45
+ NVIDIA has cuBLAS with 152 optimized routines. Trainium has `torch.matmul`. That's fine for ML training but insufficient for scientific computing codes that need TRSM, SYRK, SYMM, and batched GEMM with specific transpose/scaling semantics.
46
+
47
+ trnblas closes this gap — same BLAS API surface, NKI-accelerated GEMM on Trainium, PyTorch fallback everywhere else.
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ pip install trnblas
53
+
54
+ # With Neuron hardware support
55
+ pip install trnblas[neuron]
56
+ ```
57
+
58
+ ## Usage
59
+
60
+ ```python
61
+ import torch
62
+ import trnblas
63
+
64
+ # Level 3 — Matrix multiply (the hot path)
65
+ C = trnblas.gemm(alpha=1.0, A=A, B=B, beta=0.5, C=C_init, transA=True)
66
+
67
+ # Batched GEMM (DF-MP2 tensor contractions)
68
+ C = trnblas.batched_gemm(1.0, A_batch, B_batch)
69
+
70
+ # Symmetric matrix multiply (Fock builds)
71
+ F = trnblas.symm(1.0, density, H_core, side="left")
72
+
73
+ # Triangular solve (Cholesky-based density fitting)
74
+ X = trnblas.trsm(1.0, L, B, uplo="lower")
75
+
76
+ # Symmetric rank-k update (metric construction)
77
+ J = trnblas.syrk(1.0, integrals, trans=True)
78
+
79
+ # Level 2 — Matrix-vector
80
+ y = trnblas.gemv(1.0, A, x, beta=1.0, y=y)
81
+
82
+ # Level 1 — Vector operations
83
+ y = trnblas.axpy(alpha, x, y)
84
+ d = trnblas.dot(x, y)
85
+ n = trnblas.nrm2(x)
86
+ ```
87
+
88
+ ## DF-MP2 Example
89
+
90
+ ```bash
91
+ # Run the density-fitted MP2 example (Janesko/TCU use case)
92
+ python examples/df_mp2.py --demo
93
+ python examples/df_mp2.py --nbasis 100 --nocc 20
94
+ ```
95
+
96
+ The example demonstrates all core BLAS operations in a realistic quantum chemistry workflow: Cholesky factorization, triangular solve, half-transform GEMMs, metric contraction, and energy evaluation.
97
+
98
+ ## Operations
99
+
100
+ | Level | Operation | Description |
101
+ |-------|-----------|-------------|
102
+ | 1 | `axpy` | y = αx + y |
103
+ | 1 | `dot` | x^T y |
104
+ | 1 | `nrm2` | ‖x‖₂ |
105
+ | 1 | `scal` | x = αx |
106
+ | 1 | `asum` | Σ\|xᵢ\| |
107
+ | 1 | `iamax` | argmax \|xᵢ\| |
108
+ | 2 | `gemv` | y = α op(A) x + βy |
109
+ | 2 | `symv` | y = α A x + βy (A symmetric) |
110
+ | 2 | `trmv` | x = op(A) x (A triangular) |
111
+ | 2 | `ger` | A = α x yᵀ + A |
112
+ | 3 | `gemm` | C = α op(A) op(B) + βC |
113
+ | 3 | `batched_gemm` | Batched GEMM |
114
+ | 3 | `symm` | C = α A B + βC (A symmetric) |
115
+ | 3 | `syrk` | C = α A Aᵀ + βC |
116
+ | 3 | `trsm` | Solve op(A) X = αB |
117
+ | 3 | `trmm` | B = α op(A) B |
118
+
119
+ ## Status
120
+
121
+ - [x] Level 1-3 BLAS with PyTorch backend
122
+ - [x] GEMM with NKI dispatch stub
123
+ - [x] DF-MP2 example (Janesko/TCU use case)
124
+ - [ ] NKI GEMM kernel validation on trn1/trn2
125
+ - [ ] NKI GEMM with stationary tile reuse
126
+ - [ ] Batched GEMM NKI kernel
127
+ - [ ] Double-double FP64 emulation
128
+ - [ ] Benchmarks vs cuBLAS
129
+
130
+ ## Related Projects
131
+
132
+ | Project | What |
133
+ |---------|------|
134
+ | [trnfft](https://github.com/scttfrdmn/trnfft) | FFT + complex ops for Trainium (Williamson/OSU use case) |
135
+ | trnsolver *(planned)* | Linear solvers and eigendecomposition |
136
+
137
+ ## License
138
+
139
+ Apache 2.0 — Playground Logic LLC
@@ -0,0 +1,11 @@
1
+ trnblas/__init__.py,sha256=ZKCqCn3hyUm6zMdkdvjziyf6rdAte84ggrmzWp20WIc,1043
2
+ trnblas/level1.py,sha256=3XVIacU0ZJkF5lTYuN-j4AU-2p9ZqCV7uGZXLn4S-h0,1044
3
+ trnblas/level2.py,sha256=pbdxD1Dh37Whga7f1foVUIrmIq8lN_y3LKBX-VGh-c8,2059
4
+ trnblas/level3.py,sha256=k6dCFMsJCs8sj38GfWGmVBkMuaKkDYU03vfTCr3nBYQ,5782
5
+ trnblas/nki/__init__.py,sha256=IOVhXRydqjqRG2XHYGqqSA9wuyGQAN-IclX0mDPmVik,190
6
+ trnblas/nki/dispatch.py,sha256=qDdEdQ1MQZKkt1GvghNpFzRZWM3YcSkBeqaBTUdOVv8,3815
7
+ trnblas-0.2.0.dist-info/licenses/LICENSE,sha256=56AI7gGqh5OTpJf3y7nJVeWAY67dDH3l_CsDmdRYRog,749
8
+ trnblas-0.2.0.dist-info/METADATA,sha256=ua4gNkBef_tnxPvRqrGpQrr8tbgDbE-Xv02p6K0DGdw,4762
9
+ trnblas-0.2.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
10
+ trnblas-0.2.0.dist-info/top_level.txt,sha256=sUhvzYD9c6aMPJncvKmDoqdSqUy604F-qtzICWbj4SY,8
11
+ trnblas-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,17 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Copyright 2026 Playground Logic LLC
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
@@ -0,0 +1 @@
1
+ trnblas