import struct
import sys
TILE = 512
K = 16
M = 112
MAGIC = 0x45545157
def main():
import os
target = "simulator"
if len(sys.argv) == 3 and sys.argv[1] == "--target":
target = sys.argv[2]
elif len(sys.argv) != 1:
print(__doc__, file=sys.stderr)
return 2
if not target.replace("-", "").isalnum():
print(f"a target is letters, digits and hyphens: {target!r}", file=sys.stderr)
return 2
if target != "simulator":
os.environ.setdefault("NEURON_PLATFORM_TARGET_OVERRIDE", target)
import numpy as np
import ml_dtypes
import nki
import nki.isa as nisa
import nki.language as nl
@nki.jit
def coefficients(w, a):
tiles = a.shape[1] // TILE
out = nl.ndarray((M, a.shape[1]), dtype=nl.float32, buffer=nl.shared_hbm)
ws = nl.load(w)
for t in nl.affine_range(tiles):
xs = nl.load(a[:, t * TILE:(t + 1) * TILE])
acc = nl.ndarray((M, TILE), dtype=nl.float32, buffer=nl.psum)
nisa.nc_matmul(acc, ws, xs)
nl.store(out[:, t * TILE:(t + 1) * TILE], nl.copy(acc))
return out
inp, out = sys.stdin.buffer, sys.stdout.buffer
version = getattr(nki, "__version__", "unknown")
run = nki.simulate(coefficients) if target == "simulator" else coefficients
out.write(f"wq-tensor-engine 1 {target} nki {version} numpy {np.__version__} ml_dtypes {ml_dtypes.__version__}\n".encode())
out.flush()
def read(n):
b = inp.read(n)
if len(b) != n:
raise EOFError
return b
while True:
try:
magic, n = struct.unpack("<II", read(8))
except EOFError:
return
try:
if magic != MAGIC or n == 0 or n % TILE:
raise ValueError(f"a request of {n} pairs (magic {magic:#x})")
w = np.frombuffer(read(K * M * 2), "<u2").view(ml_dtypes.bfloat16).reshape(K, M)
a = np.frombuffer(read(K * n * 2), "<u2").view(ml_dtypes.bfloat16).reshape(K, n)
c = np.asarray(run(w, a), dtype=np.float32)
out.write(struct.pack("<I", 0))
out.write(np.ascontiguousarray(c, dtype="<f4").tobytes())
except EOFError:
return
except Exception as e: msg = f"{type(e).__name__}: {e}".encode()
out.write(struct.pack("<II", 1, len(msg)) + msg)
out.flush()
if __name__ == "__main__":
sys.exit(main())