story: DGR-030 Add accelerator build presets and native CI matrix
This commit is contained in:
112
scripts/native_accelerator_matrix.py
Normal file
112
scripts/native_accelerator_matrix.py
Normal file
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python3
|
||||
"""DGR-030: native CI/build matrix over the CPU default plus accelerator lanes.
|
||||
|
||||
Runs the exact deterministic CPU lane DGR-029 locked (unchanged), then probes
|
||||
each accelerator preset (CUDA, ROCm, Vulkan, Metal) from `UPSTREAM_LOCK.json`
|
||||
and compiles the ones whose SDK is present on this machine into their own
|
||||
out-of-tree build directory.
|
||||
|
||||
A lane whose SDK is absent is reported as `skipped` with the exact probe
|
||||
reason, never treated as a false pass. A lane that compiles is reported as
|
||||
`built`, carrying exact compiler/SDK/upstream-pin/patch-stack/build-option
|
||||
evidence — never as a certified capability. This script never runs an
|
||||
accelerator binary and never certifies a backend/model/recipe: real-hardware
|
||||
certification is separate future work (DGR-041/053/067).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT / "scripts"))
|
||||
import llama_cpp_dependency as dep # noqa: E402
|
||||
|
||||
|
||||
def _cpu_lane(source: pathlib.Path, workspace: pathlib.Path) -> dict[str, Any]:
|
||||
build_dir = workspace.resolve() / "build"
|
||||
if build_dir.exists():
|
||||
return {
|
||||
"lane": "cpu",
|
||||
"status": "skipped",
|
||||
"reason": f"build directory already exists; remove for a clean rebuild: {build_dir}",
|
||||
}
|
||||
binary = dep.build(source, build_dir)
|
||||
dep.smoke(binary)
|
||||
dep.ctest_lane(build_dir)
|
||||
metadata = json.loads((build_dir / "meshnet-build-metadata.json").read_text())
|
||||
return {"lane": "cpu", "status": "built", "build_dir": str(build_dir), "metadata": metadata}
|
||||
|
||||
|
||||
def _accelerator_lane(source: pathlib.Path, workspace: pathlib.Path, name: str, lock: dict[str, Any]) -> dict[str, Any]:
|
||||
status = dep.accelerator_status(name, lock)
|
||||
if not status["available"]:
|
||||
return {"lane": name, "status": "skipped", "reason": status["reason"]}
|
||||
build_dir = workspace.resolve() / f"build-{name}"
|
||||
if build_dir.exists():
|
||||
return {
|
||||
"lane": name,
|
||||
"status": "skipped",
|
||||
"reason": f"build directory already exists; remove for a clean rebuild: {build_dir}",
|
||||
}
|
||||
dep.accelerator_build(source, name, build_dir)
|
||||
metadata = json.loads((build_dir / "meshnet-build-metadata.json").read_text())
|
||||
return {"lane": name, "status": "built", "build_dir": str(build_dir), "metadata": metadata}
|
||||
|
||||
|
||||
def run_matrix(workspace: pathlib.Path) -> dict[str, Any]:
|
||||
"""Fetch/apply once, run every lane, then always reverse the checkout."""
|
||||
source = dep.fetch(workspace)
|
||||
dep.apply(source)
|
||||
lanes: list[dict[str, Any]] = []
|
||||
try:
|
||||
lock = dep._load_lock()
|
||||
try:
|
||||
lanes.append(_cpu_lane(source, workspace))
|
||||
except dep.DependencyError as error:
|
||||
lanes.append({"lane": "cpu", "status": "failed", "reason": str(error)})
|
||||
for name in lock.get("accelerator_presets", {}):
|
||||
try:
|
||||
lanes.append(_accelerator_lane(source, workspace, name, lock))
|
||||
except dep.DependencyError as error:
|
||||
lanes.append({"lane": name, "status": "failed", "reason": str(error)})
|
||||
finally:
|
||||
dep.reverse(source)
|
||||
failed_lanes = [lane["lane"] for lane in lanes if lane["status"] == "failed"]
|
||||
return {
|
||||
"lanes": lanes,
|
||||
"hardware_certified": False,
|
||||
"note": (
|
||||
"A `built` lane means it compiled with the exact recorded compiler/SDK/"
|
||||
"upstream-pin/patch-stack/build-option evidence — it never means an "
|
||||
"accelerator device was exercised. Every backend/model/recipe lane "
|
||||
"stays registered-dark until a separate real-hardware certification "
|
||||
"record exists."
|
||||
),
|
||||
"failed_lanes": failed_lanes,
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--workspace", type=pathlib.Path, default=ROOT / "build/llama.cpp")
|
||||
parser.add_argument("--out", type=pathlib.Path, default=None, help="also write the JSON report here")
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
report = run_matrix(args.workspace)
|
||||
except dep.DependencyError as error:
|
||||
print(f"DGR-030 dependency error: {error}", file=sys.stderr)
|
||||
return 2
|
||||
text = json.dumps(report, indent=2, sort_keys=True)
|
||||
print(text)
|
||||
if args.out:
|
||||
args.out.write_text(text + "\n")
|
||||
return 1 if report["failed_lanes"] else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user