Files
Raptor/test/PIM/test_PimEmission.py
T

92 lines
4.7 KiB
Python

"""Intermediate emission must stop before unsupported backend transformations."""
import argparse
import json
import os
from pathlib import Path
import subprocess
import tempfile
import onnx
from onnx import TensorProto, helper
REPO = Path(__file__).resolve().parents[2]
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--compiler", required=True)
args = parser.parse_args()
with tempfile.TemporaryDirectory(prefix="raptor-emission-") as temporary:
root = Path(temporary)
def model(name, elements):
tensors = [helper.make_tensor_value_info(n, TensorProto.FLOAT, [1, elements])
for n in ("x", "y", "z")]
graph = helper.make_graph([helper.make_node("Add", ["x", "y"], ["z"])],
name, tensors[:2], tensors[2:])
value = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 18)])
value.ir_version = 10
path = root / f"{name}.onnx"
onnx.save(value, path)
return path
small = model("small", 16)
# This static type is legal in Spatial. PIM's signed byte-size operand cannot encode it.
large = model("large", 536870912)
for source, targets in ((small, ("EmitSpatial", "EmitPim", "EmitPimBufferized", "EmitPimCodegen")),
(large, ("EmitSpatial", "EmitPim"))):
for target in targets:
out = root / source.stem / target
out.mkdir(parents=True)
result = subprocess.run([args.compiler, str(source), "-o", str(out / "model"),
"--maccel=PIM", f"--{target}", "--pipeline=2", "--core-count=168",
"--crossbar-count=96", "--crossbar-size=128", "--mlir-disable-threading", "--pim-dump-ir",
f"--pim-target-config={REPO}/validation/pimsim_configs/pimcomp/arch-a/throughput_config_1000ms.json"],
capture_output=True, text=True, timeout=30, env=dict(os.environ, OMP_NUM_THREADS="1"))
output = result.stdout + result.stderr
if source == large and target == "EmitPim":
assert result.returncode != 0 and "host input copy byte size is outside representable range" in output, output
continue
assert result.returncode == 0, output
if target == "EmitPimCodegen":
assert (out / "pim/config.json").exists()
report = json.loads((out / "reports/pipeline_selection.json").read_text())
assert report["generated_candidates"] == 1
assert report["single_candidate_analysis_skipped"]
assert report["lowered_candidates"] == 1
assert "no cost comparison required" in report["reason"]
else:
assert "intermediate emission retains the original schedule" in output
assert not (out / "reports/pipeline_selection.json").exists()
assert not (out / "reports/pipeline_periodic.json").exists()
assert not (out / "pim").exists()
name = {"EmitSpatial": "spatial4_scheduled", "EmitPim": "pim0",
"EmitPimBufferized": "pim1_buff"}[target]
ir = (out / f"dialects/{name}.mlir").read_text()
if target == "EmitSpatial":
assert "spat.scheduled_compute" in ir and "pim.core" not in ir
assert not (out / "dialects/pim0.mlir").exists()
elif target == "EmitPim":
assert "pim.core" in ir and "tensor<" in ir
assert not (out / "dialects/pim1_buff.mlir").exists()
else:
assert "pim.core" in ir and "memref<" in ir
out = root / "explicit-diagnostic"
out.mkdir()
result = subprocess.run([args.compiler, str(small), "-o", str(out / "model"),
"--maccel=PIM", "--EmitSpatial", "--pipeline=2", "--core-count=168",
"--crossbar-count=96", "--crossbar-size=128", "--mlir-disable-threading",
"--pim-periodic-diagnostics",
f"--pim-target-config={REPO}/validation/pimsim_configs/pimcomp/arch-a/throughput_config_1000ms.json"],
capture_output=True, text=True, timeout=30)
assert result.returncode == 0, result.stdout + result.stderr
assert (out / "reports/pipeline_periodic.json").exists()
report = json.loads((out / "reports/pipeline_periodic.json").read_text())
assert report["diagnostic_only"]
assert not report["selection_eligible"]
assert not (out / "pim").exists()
if __name__ == "__main__":
main()