4a1fe710b2
Validate Operations / validate-operations (push) Has been cancelled
increase throughput scheduler budget add experimental throughput auto mode
108 lines
5.5 KiB
Python
108 lines
5.5 KiB
Python
"""Spatial selection lowers one winner and rejects incomplete comparisons."""
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import shutil
|
|
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-spatial-selection-") as temporary:
|
|
root = Path(temporary)
|
|
guard = root / "static-audit.so"
|
|
subprocess.run([os.environ.get("CC", "cc"), "-shared", "-fPIC",
|
|
str(REPO / "test/PIM/StaticSchedulingAudit.c"), "-o", str(guard)], check=True)
|
|
env = dict(os.environ, LD_PRELOAD=str(guard), OMP_NUM_THREADS="1")
|
|
iteration = 0
|
|
|
|
def compile(source, pipeline=2, emit="EmitPimCodegen", extra=(), succeeds=True):
|
|
nonlocal iteration
|
|
output = root / str(iteration)
|
|
iteration += 1
|
|
output.mkdir()
|
|
command = [args.compiler, str(source), "-o", str(output / "model"), "--maccel=PIM",
|
|
f"--{emit}", f"--pipeline={pipeline}", "--core-count=138", "--crossbar-count=128",
|
|
"--crossbar-size=128", "--mlir-disable-threading", "--pim-detect-communication-deadlock",
|
|
f"--pim-target-config={REPO}/validation/pimsim_configs/pimcomp/arch-b/throughput_config_1000ms.json"]
|
|
command.extend(extra)
|
|
result = subprocess.run(command, env=env, capture_output=True, text=True, timeout=120)
|
|
assert (result.returncode == 0) == succeeds, result.stdout + result.stderr
|
|
path = output / "reports/pipeline_selection.json"
|
|
report = json.loads(path.read_text()) if path.exists() else None
|
|
program = {str(p.relative_to(output / "pim")): hashlib.sha256(p.read_bytes()).hexdigest()
|
|
for p in (output / "pim").rglob("*") if p.is_file()}
|
|
if "--pim-export-spatial-dataflow=all" in extra:
|
|
for stage in ("spatial3_scheduled_no_comm", "spatial4_scheduled"):
|
|
for suffix in ("nodes.csv", "edges.csv"):
|
|
assert (output / f"reports/{stage}.{suffix}").stat().st_size > 0
|
|
assert (output / "dialects/spatial4_scheduled.mlir").exists()
|
|
assert (output / "dialects/pim1_buff.mlir").exists()
|
|
shutil.rmtree(output)
|
|
return report, program, result.stdout + result.stderr
|
|
|
|
vgg = REPO / "validation/networks/pimcomp_models/vgg8/vgg8-mnist-reconstructed.onnx"
|
|
selected, program, _ = compile(vgg)
|
|
count = selected["generated_candidates"]
|
|
assert count > 1 and selected["strategy"] == "spatial-queue-aware"
|
|
assert selected["lowered_candidates"] == 1
|
|
assert len(selected["backend_attempts"]) == 1
|
|
assert selected["backend_attempts"][0]["candidate"] == selected["selection"]
|
|
assert not selected["prediction_error_bound_available"]
|
|
assert selected["selection_margin"] == 0.021
|
|
for candidate in selected["candidates"]:
|
|
assert candidate["cost_available"] and candidate["convergence_proved"]
|
|
assert candidate["lowering_supported"] and candidate["eligible"]
|
|
assert "request_order" not in candidate["spatial_cost"]
|
|
assert "without_local_copy_work" not in candidate["spatial_cost"]
|
|
diagnostic, diagnostic_program, _ = compile(vgg, extra=(
|
|
"--pim-export-spatial-dataflow=all", "--pim-dump-ir", "--pim-periodic-diagnostics"))
|
|
assert diagnostic_program == program and diagnostic["selection"] == selected["selection"]
|
|
|
|
# Softmax remains in the functional program but has no oracle timing work.
|
|
model = onnx.load(vgg)
|
|
output = model.graph.output[0].name
|
|
internal = output + "_before_softmax"
|
|
for node in model.graph.node:
|
|
for index, value in enumerate(node.output):
|
|
if value == output:
|
|
node.output[index] = internal
|
|
for index, value in enumerate(node.input):
|
|
if value == output:
|
|
node.input[index] = internal
|
|
model.graph.node.append(helper.make_node("Softmax", [internal], [output], axis=-1))
|
|
source = root / "vgg-softmax.onnx"
|
|
onnx.save(model, source)
|
|
report, program, _ = compile(source)
|
|
assert report["generated_candidates"] > 1 and report["status"] == "selected"
|
|
assert report["lowered_candidates"] == 1 and program
|
|
assert all(candidate["eligible"] for candidate in report["candidates"])
|
|
|
|
# An unknown estimate cannot silently exclude any alternative.
|
|
source = REPO / "validation/operations/matmul/yolo_attention/matmul_yolo_attention.onnx"
|
|
report, program, diagnostics = compile(source, succeeds=False)
|
|
assert report["generated_candidates"] >= 1 and report["status"] == "incomplete-costs"
|
|
assert "cannot compare the complete candidate set" in diagnostics
|
|
assert "unavailable indirect" in diagnostics
|
|
assert not program and "backend_attempts" not in report
|
|
# Latency PEFT and earlier emission do not invoke candidate costing.
|
|
report, program, _ = compile(vgg, pipeline=1)
|
|
assert report is None and program
|
|
report, program, stderr = compile(vgg, emit="EmitSpatial")
|
|
assert report is None and not program
|
|
assert "intermediate emission retains the original schedule" in stderr
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|