from __future__ import annotations
import json
import os
import tempfile
import unittest
from pathlib import Path
from unittest import mock
from presmoke.cli import (
detect_cpu_count,
main,
resolve_cpu_build_jobs,
resolve_cpu_run_slots,
resolve_jobs,
resolve_make_jobs,
)
from presmoke.model import Cell, Command, ExampleSpec
from presmoke.scheduler import (
custom_op_dependency_violation_s,
export_schedule_file,
schedule_cells,
ScheduleOptions,
simulate_npu_idle,
simulate_npu_makespan,
)
def cell(tmp: Path, name: str) -> Cell:
spec = ExampleSpec(tmp / name, name, [Command(":", "build")], ["dav-2201"], ["npu"], "test")
spec.path.mkdir(parents=True, exist_ok=True)
return Cell(spec, "dav-2201", "npu", spec.commands, spec.path / "build_npu")
def write_timing_report(path: Path, timings: dict[str, tuple[float, float]]) -> None:
path.write_text(
json.dumps(
{
"results": [
{
"example": example,
"steps": [
{"kind": "build", "duration_s": build_s},
{"kind": "run", "duration_s": run_s},
],
}
for example, (build_s, run_s) in timings.items()
]
}
),
encoding="utf-8",
)
class SchedulerTest(unittest.TestCase):
def test_default_schedule_keeps_original_order(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
cells = [cell(root, "a"), cell(root, "b"), cell(root, "c")]
scheduled = schedule_cells(cells)
self.assertEqual([item.example.rel_path for item in scheduled], ["a", "b", "c"])
def test_custom_op_static_lib_is_always_before_custom_op(self) -> None:
custom_op = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op"
static_lib = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op_static_lib"
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
cells = [cell(root, "a"), cell(root, custom_op), cell(root, "b"), cell(root, static_lib)]
scheduled = schedule_cells(cells)
names = [item.example.rel_path for item in scheduled]
self.assertLess(names.index(static_lib), names.index(custom_op))
def test_parallel_ops_package_is_always_after_custom_op_static_lib(self) -> None:
static_lib = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op_static_lib"
parallel_ops = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/parallel_ops_package"
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
cells = [cell(root, parallel_ops), cell(root, "a"), cell(root, static_lib)]
scheduled = schedule_cells(cells)
names = [item.example.rel_path for item in scheduled]
self.assertLess(names.index(static_lib), names.index(parallel_ops))
def test_required_order_survives_build_desc_schedule(self) -> None:
custom_op = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op"
static_lib = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op_static_lib"
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
report = root / "report.json"
report.write_text(
json.dumps(
{
"results": [
{"example": custom_op, "steps": [{"kind": "build", "duration_s": 100}]},
{"example": static_lib, "steps": [{"kind": "build", "duration_s": 1}]},
]
}
),
encoding="utf-8",
)
cells = [cell(root, custom_op), cell(root, "a"), cell(root, static_lib)]
scheduled = schedule_cells(cells, ScheduleOptions(schedule="build-desc", schedule_report=report))
names = [item.example.rel_path for item in scheduled]
self.assertLess(names.index(static_lib), names.index(custom_op))
def test_custom_op_dependents_are_always_after_custom_op(self) -> None:
custom_op = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op"
dependents = [
"01_simd_cpp_api/02_features/99_acl_based/01_acl_invocation/aclnn_invocation",
"01_simd_cpp_api/02_features/99_acl_based/01_acl_invocation/aclop_invocation",
"01_simd_cpp_api/02_features/00_framework/01_tensorflow/tensorflow_builtin",
"01_simd_cpp_api/02_features/00_framework/01_tensorflow/tensorflow_custom",
"01_simd_cpp_api/02_features/00_framework/02_onnx/onnx_plugin",
"04_aicpu/02_features/00_framwork/00_pytorch/tiling_sink_programming",
]
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
cells = [
cell(root, dependents[0]),
cell(root, "a"),
cell(root, dependents[1]),
cell(root, custom_op),
cell(root, dependents[2]),
cell(root, dependents[3]),
cell(root, dependents[4]),
cell(root, dependents[5]),
]
scheduled = schedule_cells(cells)
names = [item.example.rel_path for item in scheduled]
for dependent in dependents:
self.assertLess(names.index(custom_op), names.index(dependent))
def test_npu_idle_min_preserves_custom_op_required_order(self) -> None:
custom_op = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op"
static_lib = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op_static_lib"
dependent = "01_simd_cpp_api/02_features/00_framework/02_onnx/onnx_plugin"
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
report = root / "report.json"
write_timing_report(
report,
{
dependent: (1, 30),
custom_op: (2, 1),
static_lib: (100, 1),
},
)
cells = [cell(root, dependent), cell(root, custom_op), cell(root, static_lib)]
scheduled = schedule_cells(cells, ScheduleOptions(schedule="npu-idle-min", schedule_report=report, jobs=2))
names = [item.example.rel_path for item in scheduled]
self.assertLess(names.index(static_lib), names.index(custom_op))
self.assertLess(names.index(custom_op), names.index(dependent))
def test_npu_idle_min_delays_custom_op_dependents_until_custom_op_build_ready(self) -> None:
custom_op = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op"
static_lib = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op_static_lib"
dependent = "04_aicpu/02_features/00_framwork/00_pytorch/tiling_sink_programming"
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
report = root / "report.json"
write_timing_report(
report,
{
static_lib: (1, 1),
custom_op: (30, 1),
dependent: (1, 10),
"short-a": (1, 10),
"short-b": (1, 10),
"short-c": (1, 10),
"short-d": (1, 10),
"short-e": (1, 10),
},
)
cells = [
cell(root, static_lib),
cell(root, custom_op),
cell(root, dependent),
cell(root, "short-a"),
cell(root, "short-b"),
cell(root, "short-c"),
cell(root, "short-d"),
cell(root, "short-e"),
]
scheduled = schedule_cells(cells, ScheduleOptions(schedule="npu-idle-min", schedule_report=report, jobs=4))
self.assertEqual(custom_op_dependency_violation_s(scheduled, report, jobs=4), 0.0)
def test_build_desc_schedule_uses_historical_build_duration(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
report = root / "report.json"
report.write_text(
json.dumps(
{
"results": [
{
"example": "a",
"steps": [
{"kind": "clean", "duration_s": 1},
{"kind": "build", "duration_s": 10},
],
},
{"example": "b", "steps": [{"kind": "build", "duration_s": 2}]},
]
}
),
encoding="utf-8",
)
cells = [cell(root, "c"), cell(root, "b"), cell(root, "a")]
scheduled = schedule_cells(cells, ScheduleOptions(schedule="build-desc", schedule_report=report))
self.assertEqual([item.example.rel_path for item in scheduled], ["a", "b", "c"])
self.assertIsInstance(scheduled[0], Cell)
def test_frontload_build_desc_keeps_rest_in_original_order(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
report = root / "report.json"
report.write_text(
json.dumps(
{
"results": [
{"example": "slow", "steps": [{"kind": "build", "duration_s": 30}]},
{"example": "medium", "steps": [{"kind": "build", "duration_s": 20}]},
]
}
),
encoding="utf-8",
)
cells = [cell(root, "fast-a"), cell(root, "slow"), cell(root, "fast-b"), cell(root, "medium")]
scheduled = schedule_cells(
cells,
ScheduleOptions(
schedule="frontload-build-desc",
schedule_report=report,
frontload_count=1,
),
)
self.assertEqual([item.example.rel_path for item in scheduled], ["slow", "fast-a", "fast-b", "medium"])
def test_fixed_schedule_uses_schedule_file_and_appends_missing_cases(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
schedule_file = root / "schedule.txt"
schedule_file.write_text("b\n# comment\nunknown\n\na\n", encoding="utf-8")
cells = [cell(root, name) for name in ["a", "b", "c"]]
scheduled = schedule_cells(cells, ScheduleOptions(schedule="fixed", schedule_file=schedule_file))
self.assertEqual([item.example.rel_path for item in scheduled], ["b", "a", "c"])
def test_fixed_schedule_preserves_custom_op_required_order(self) -> None:
custom_op = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op"
static_lib = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/custom_op_static_lib"
dependent = "01_simd_cpp_api/02_features/00_framework/02_onnx/onnx_plugin"
parallel_ops = "01_simd_cpp_api/02_features/99_acl_based/00_acl_compilation/parallel_ops_package"
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
schedule_file = root / "schedule.txt"
schedule_file.write_text(f"{dependent}\n{custom_op}\n{parallel_ops}\n{static_lib}\n", encoding="utf-8")
cells = [cell(root, dependent), cell(root, custom_op), cell(root, parallel_ops), cell(root, static_lib)]
scheduled = schedule_cells(cells, ScheduleOptions(schedule="fixed", schedule_file=schedule_file))
names = [item.example.rel_path for item in scheduled]
self.assertLess(names.index(static_lib), names.index(custom_op))
self.assertLess(names.index(static_lib), names.index(parallel_ops))
self.assertLess(names.index(custom_op), names.index(dependent))
def test_fixed_schedule_requires_existing_schedule_file(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
cells = [cell(root, "a")]
with self.assertRaises(FileNotFoundError):
schedule_cells(cells, ScheduleOptions(schedule="fixed", schedule_file=root / "missing.txt"))
def test_export_schedule_file_writes_selected_order(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
report = root / "report.json"
write_timing_report(report, {"slow-a": (100, 1), "fast-a": (1, 30), "fast-b": (1, 20)})
out = root / "fixed.txt"
cells = [cell(root, name) for name in ["slow-a", "fast-a", "fast-b"]]
export_schedule_file(cells, out)
self.assertEqual(out.read_text(encoding="utf-8").splitlines(), ["slow-a", "fast-a", "fast-b"])
def test_cli_applies_schedule_before_dry_run(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
for name in ["a", "b", "c"]:
runner = root / "scripts" / "presmoke" / "cases" / name / "run.sh"
runner.parent.mkdir(parents=True, exist_ok=True)
runner.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
manifest = root / "scripts" / "presmoke" / "reports" / "case_runner_manifest.json"
manifest.parent.mkdir(parents=True, exist_ok=True)
manifest.write_text(
json.dumps(
[
{"case": "c", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "b", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "a", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
]
),
encoding="utf-8",
)
schedule_report = root / "schedule_report.json"
schedule_report.write_text(
json.dumps(
{
"results": [
{"example": "a", "steps": [{"kind": "build", "duration_s": 30}]},
{"example": "b", "steps": [{"kind": "build", "duration_s": 10}]},
]
}
),
encoding="utf-8",
)
results_dir = root / "out"
with mock.patch.dict(os.environ, {"PRESMOKE_PROJECT_ROOT": str(root)}):
rc = main(
[
"--runner-mode",
"case-runner",
"--arch",
"dav-2201",
"--modes",
"npu",
"--dry-run",
"--schedule",
"build-desc",
"--schedule-report",
str(schedule_report),
"--report-format",
"json",
"--results",
str(results_dir),
]
)
payload = json.loads((results_dir / "report.json").read_text(encoding="utf-8"))
self.assertEqual(rc, 0)
self.assertEqual([item["example"] for item in payload["results"]], ["a", "b", "c"])
def test_cli_fixed_schedule_uses_builtin_schedule_file(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
for name in ["a", "b", "c"]:
runner = root / "scripts" / "presmoke" / "cases" / name / "run.sh"
runner.parent.mkdir(parents=True, exist_ok=True)
runner.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
manifest = root / "scripts" / "presmoke" / "reports" / "case_runner_manifest.json"
manifest.parent.mkdir(parents=True, exist_ok=True)
manifest.write_text(
json.dumps(
[
{"case": "a", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "b", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "c", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
]
),
encoding="utf-8",
)
schedule_file = root / "scripts" / "presmoke" / "schedules" / "dav-2201_npu.txt"
schedule_file.parent.mkdir(parents=True, exist_ok=True)
schedule_file.write_text("b\na\n", encoding="utf-8")
results_dir = root / "out"
with mock.patch.dict(os.environ, {"PRESMOKE_PROJECT_ROOT": str(root)}):
rc = main(
[
"--runner-mode",
"case-runner",
"--arch",
"dav-2201",
"--modes",
"npu",
"--dry-run",
"--schedule",
"fixed",
"--report-format",
"json",
"--results",
str(results_dir),
]
)
payload = json.loads((results_dir / "report.json").read_text(encoding="utf-8"))
self.assertEqual(rc, 0)
self.assertEqual([item["example"] for item in payload["results"]], ["b", "a", "c"])
def test_cli_strict_fixed_schedule_rejects_schedule_only_cases(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
for name in ["a", "b"]:
runner = root / "scripts" / "presmoke" / "cases" / name / "run.sh"
runner.parent.mkdir(parents=True, exist_ok=True)
runner.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
manifest = root / "scripts" / "presmoke" / "reports" / "case_runner_manifest.json"
manifest.parent.mkdir(parents=True, exist_ok=True)
manifest.write_text(
json.dumps(
[
{"case": "a", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "b", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
]
),
encoding="utf-8",
)
schedule_file = root / "scripts" / "presmoke" / "schedules" / "dav-2201_npu.txt"
schedule_file.parent.mkdir(parents=True, exist_ok=True)
schedule_file.write_text("a\nb\nmissing\n", encoding="utf-8")
with mock.patch.dict(os.environ, {"PRESMOKE_PROJECT_ROOT": str(root)}):
rc = main(
[
"--runner-mode",
"case-runner",
"--arch",
"dav-2201",
"--modes",
"npu",
"--dry-run",
"--schedule",
"fixed",
"--strict-schedule",
"--report-format",
"json",
"--results",
str(root / "out"),
]
)
self.assertEqual(rc, 2)
def test_cli_strict_fixed_schedule_rejects_unscheduled_planned_cases(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
for name in ["a", "b", "new-case"]:
runner = root / "scripts" / "presmoke" / "cases" / name / "run.sh"
runner.parent.mkdir(parents=True, exist_ok=True)
runner.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
manifest = root / "scripts" / "presmoke" / "reports" / "case_runner_manifest.json"
manifest.parent.mkdir(parents=True, exist_ok=True)
manifest.write_text(
json.dumps(
[
{"case": "a", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "b", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "new-case", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
]
),
encoding="utf-8",
)
schedule_file = root / "scripts" / "presmoke" / "schedules" / "dav-2201_npu.txt"
schedule_file.parent.mkdir(parents=True, exist_ok=True)
schedule_file.write_text("a\nb\n", encoding="utf-8")
with mock.patch.dict(os.environ, {"PRESMOKE_PROJECT_ROOT": str(root)}):
rc = main(
[
"--runner-mode",
"case-runner",
"--arch",
"dav-2201",
"--modes",
"npu",
"--dry-run",
"--schedule",
"fixed",
"--strict-schedule",
"--report-format",
"json",
"--results",
str(root / "out"),
]
)
self.assertEqual(rc, 2)
def test_cli_fixed_schedule_falls_back_when_builtin_cpu_schedule_is_missing(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
for name in ["a", "b"]:
runner = root / "scripts" / "presmoke" / "cases" / name / "run.sh"
runner.parent.mkdir(parents=True, exist_ok=True)
runner.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
manifest = root / "scripts" / "presmoke" / "reports" / "case_runner_manifest.json"
manifest.parent.mkdir(parents=True, exist_ok=True)
manifest.write_text(
json.dumps(
[
{"case": "a", "supported_archs": ["dav-2201"], "supported_modes": ["cpu"]},
{"case": "b", "supported_archs": ["dav-2201"], "supported_modes": ["cpu"]},
]
),
encoding="utf-8",
)
results_dir = root / "out"
with mock.patch.dict(os.environ, {"PRESMOKE_PROJECT_ROOT": str(root)}):
rc = main(
[
"--runner-mode",
"case-runner",
"--arch",
"dav-2201",
"--modes",
"cpu",
"--dry-run",
"--schedule",
"fixed",
"--report-format",
"json",
"--results",
str(results_dir),
]
)
payload = json.loads((results_dir / "report.json").read_text(encoding="utf-8"))
self.assertEqual(rc, 0)
self.assertEqual([item["example"] for item in payload["results"]], ["a", "b"])
def test_builtin_910b_npu_schedule_matches_manifest(self) -> None:
project_root = Path(__file__).resolve().parents[3]
manifest_path = project_root / "scripts" / "presmoke" / "reports" / "case_runner_manifest.json"
schedule_path = project_root / "scripts" / "presmoke" / "schedules" / "dav-2201_npu.txt"
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
planned = {
item["case"]
for item in manifest
if item.get("target_runnable", True)
and "dav-2201" in item.get("supported_archs", [])
and "npu" in item.get("supported_modes", [])
}
scheduled = {
line.strip()
for line in schedule_path.read_text(encoding="utf-8").splitlines()
if line.strip() and not line.lstrip().startswith("#")
}
self.assertEqual(scheduled - planned, set())
self.assertEqual(planned - scheduled, set())
missing_runners = [
name
for name in scheduled
if not (project_root / "scripts" / "presmoke" / "cases" / name / "run.sh").is_file()
]
self.assertEqual(missing_runners, [])
def test_cli_schedule_file_overrides_builtin_schedule_file(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
for name in ["a", "b", "c"]:
runner = root / "scripts" / "presmoke" / "cases" / name / "run.sh"
runner.parent.mkdir(parents=True, exist_ok=True)
runner.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
manifest = root / "scripts" / "presmoke" / "reports" / "case_runner_manifest.json"
manifest.parent.mkdir(parents=True, exist_ok=True)
manifest.write_text(
json.dumps(
[
{"case": "a", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "b", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "c", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
]
),
encoding="utf-8",
)
builtin = root / "scripts" / "presmoke" / "schedules" / "dav-2201_npu.txt"
builtin.parent.mkdir(parents=True, exist_ok=True)
builtin.write_text("a\nb\n", encoding="utf-8")
explicit = root / "explicit.txt"
explicit.write_text("c\nb\n", encoding="utf-8")
results_dir = root / "out"
with mock.patch.dict(os.environ, {"PRESMOKE_PROJECT_ROOT": str(root)}):
rc = main(
[
"--runner-mode",
"case-runner",
"--arch",
"dav-2201",
"--modes",
"npu",
"--dry-run",
"--schedule",
"fixed",
"--schedule-file",
str(explicit),
"--report-format",
"json",
"--results",
str(results_dir),
]
)
payload = json.loads((results_dir / "report.json").read_text(encoding="utf-8"))
self.assertEqual(rc, 0)
self.assertEqual([item["example"] for item in payload["results"]], ["c", "b", "a"])
def test_cli_export_schedule_writes_current_order(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
for name in ["a", "b", "c"]:
runner = root / "scripts" / "presmoke" / "cases" / name / "run.sh"
runner.parent.mkdir(parents=True, exist_ok=True)
runner.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
manifest = root / "scripts" / "presmoke" / "reports" / "case_runner_manifest.json"
manifest.parent.mkdir(parents=True, exist_ok=True)
manifest.write_text(
json.dumps(
[
{"case": "a", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "b", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "c", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
]
),
encoding="utf-8",
)
schedule_file = root / "schedule.txt"
schedule_file.write_text("c\na\n", encoding="utf-8")
export_path = root / "exported.txt"
with mock.patch.dict(os.environ, {"PRESMOKE_PROJECT_ROOT": str(root)}):
rc = main(
[
"--runner-mode",
"case-runner",
"--arch",
"dav-2201",
"--modes",
"npu",
"--dry-run",
"--schedule",
"fixed",
"--schedule-file",
str(schedule_file),
"--export-schedule",
str(export_path),
"--report-format",
"json",
"--results",
str(root / "out"),
]
)
exported_lines = export_path.read_text(encoding="utf-8").splitlines()
self.assertEqual(rc, 0)
self.assertEqual(exported_lines, ["c", "a", "b"])
def test_npu_idle_min_schedule_is_not_worse_than_build_desc_after_frontload(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
report = root / "report.json"
write_timing_report(
report,
{
"slow-a": (100, 1),
"slow-b": (90, 1),
"fast-a": (1, 30),
"fast-b": (1, 30),
"fast-c": (1, 30),
},
)
cells = [cell(root, name) for name in ["slow-a", "slow-b", "fast-a", "fast-b", "fast-c"]]
build_desc = schedule_cells(cells, ScheduleOptions(schedule="build-desc", schedule_report=report, jobs=2))
idle_min = schedule_cells(cells, ScheduleOptions(schedule="npu-idle-min", schedule_report=report, jobs=2))
idle_min_s = simulate_npu_idle(idle_min, report, jobs=2)
build_desc_idle_s = simulate_npu_idle(build_desc, report, jobs=2)
idle_min_makespan_s = simulate_npu_makespan(idle_min, report, jobs=2)
build_desc_makespan_s = simulate_npu_makespan(build_desc, report, jobs=2)
self.assertLessEqual(idle_min_s, build_desc_idle_s)
self.assertLessEqual(idle_min_makespan_s, build_desc_makespan_s)
def test_npu_idle_min_schedule_depends_on_jobs(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
report = root / "report.json"
write_timing_report(
report,
{
"c0": (100, 10),
"c1": (100, 10),
"c2": (1, 5),
"c3": (20, 10),
"c4": (10, 100),
"c5": (100, 5),
},
)
cells = [cell(root, name) for name in ["c0", "c1", "c2", "c3", "c4", "c5"]]
one_job = schedule_cells(cells, ScheduleOptions(schedule="npu-idle-min", schedule_report=report, jobs=1))
two_jobs = schedule_cells(cells, ScheduleOptions(schedule="npu-idle-min", schedule_report=report, jobs=2))
self.assertNotEqual([item.example.rel_path for item in one_job], [item.example.rel_path for item in two_jobs])
def test_cli_accepts_npu_idle_min_schedule_before_dry_run(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
for name in ["slow-a", "fast-a", "fast-b"]:
runner = root / "scripts" / "presmoke" / "cases" / name / "run.sh"
runner.parent.mkdir(parents=True, exist_ok=True)
runner.write_text("#!/usr/bin/env bash\nexit 0\n", encoding="utf-8")
manifest = root / "scripts" / "presmoke" / "reports" / "case_runner_manifest.json"
manifest.parent.mkdir(parents=True, exist_ok=True)
manifest.write_text(
json.dumps(
[
{"case": "slow-a", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "fast-a", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
{"case": "fast-b", "supported_archs": ["dav-2201"], "supported_modes": ["npu"]},
]
),
encoding="utf-8",
)
schedule_report = root / "schedule_report.json"
write_timing_report(schedule_report, {"slow-a": (100, 1), "fast-a": (1, 30), "fast-b": (1, 20)})
results_dir = root / "out"
with mock.patch.dict(os.environ, {"PRESMOKE_PROJECT_ROOT": str(root)}):
rc = main(
[
"--runner-mode",
"case-runner",
"--arch",
"dav-2201",
"--modes",
"npu",
"--dry-run",
"--schedule",
"npu-idle-min",
"--schedule-report",
str(schedule_report),
"--jobs",
"2",
"--report-format",
"json",
"--results",
str(results_dir),
]
)
payload = json.loads((results_dir / "report.json").read_text(encoding="utf-8"))
self.assertEqual(rc, 0)
self.assertEqual([item["example"] for item in payload["results"]], ["slow-a", "fast-a", "fast-b"])
def test_auto_jobs_scales_with_available_cpu_count(self) -> None:
self.assertEqual(resolve_jobs("auto", cpu_count=192), 12)
self.assertEqual(resolve_jobs("auto", cpu_count=88), 8)
self.assertEqual(resolve_jobs("auto", cpu_count=40), 6)
self.assertEqual(resolve_jobs("auto", cpu_count=16), 4)
self.assertEqual(resolve_jobs("7", cpu_count=192), 7)
def test_cpu_auto_jobs_use_generic_cpu_count_formula(self) -> None:
self.assertEqual(resolve_cpu_build_jobs(192), 48)
self.assertEqual(resolve_cpu_build_jobs(88), 22)
self.assertEqual(resolve_cpu_build_jobs(40), 10)
self.assertEqual(resolve_cpu_build_jobs(16), 4)
self.assertEqual(resolve_cpu_build_jobs(320), 64)
self.assertEqual(resolve_jobs("auto", cpu_count=192, modes=["cpu"]), 48)
self.assertEqual(resolve_jobs("auto", cpu_count=88, modes=["cpu"]), 22)
def test_cpu_parallel_defaults_use_host_cpu_count(self) -> None:
self.assertEqual(resolve_cpu_run_slots("auto", cpu_count=192), 192)
self.assertEqual(resolve_cpu_run_slots("5", cpu_count=192), 5)
self.assertEqual(resolve_make_jobs("auto", build_jobs=48, cpu_count=192), 4)
self.assertEqual(resolve_make_jobs("auto", build_jobs=22, cpu_count=88), 4)
self.assertEqual(resolve_make_jobs("3", build_jobs=12, cpu_count=192), 3)
def test_cli_report_includes_resolved_parallel_config(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
project = root / "project"
runner = project / "scripts/presmoke/cases/cpu-case/run.sh"
runner.parent.mkdir(parents=True)
runner.write_text("#!/usr/bin/env bash\n", encoding="utf-8")
manifest = project / "scripts/presmoke/reports/case_runner_manifest.json"
manifest.parent.mkdir(parents=True)
manifest.write_text(
'[{"case":"cpu-case","supported_archs":["dav-2201"],"supported_modes":["cpu"]}]',
encoding="utf-8",
)
results_dir = root / "results"
with mock.patch.dict(os.environ, {"PRESMOKE_PROJECT_ROOT": str(project)}):
with mock.patch("presmoke.cli.detect_cpu_count", return_value=88):
rc = main(
[
"--runner-mode",
"case-runner",
"--arch",
"dav-2201",
"--modes",
"cpu",
"--dry-run",
"--report-format",
"json",
"--results",
str(results_dir),
"--jobs",
"auto",
"--cpu-run-slots",
"auto",
"--make-jobs",
"auto",
]
)
payload = json.loads((results_dir / "report.json").read_text(encoding="utf-8"))
self.assertEqual(rc, 0)
self.assertEqual(
payload["parallel_config"],
{"jobs": 22, "npu_slots": 1, "cpu_run_slots": 88, "make_jobs": 4, "cpu_run_timeout": 300},
)
def test_detect_cpu_count_prefers_lscpu(self) -> None:
with mock.patch("presmoke.cli.shutil.which", return_value="/usr/bin/lscpu"):
with mock.patch("presmoke.cli.subprocess.run") as run:
run.return_value.stdout = "CPU(s): 192\n"
run.return_value.returncode = 0
self.assertEqual(detect_cpu_count(), 192)
run.assert_called_once()
def test_npu_idle_min_does_not_frontload_long_builds_when_it_increases_idle(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
report = root / "report.json"
timings = {
"slow-a": (500, 1),
"slow-b": (130, 1),
"slow-c": (120, 1),
"slow-d": (110, 1),
"fast-a": (1, 200),
"fast-b": (1, 100),
"fast-c": (1, 80),
"fast-d": (1, 60),
}
write_timing_report(report, timings)
cells = [
cell(root, name)
for name in ["fast-a", "fast-b", "fast-c", "fast-d", "slow-a", "slow-b", "slow-c", "slow-d"]
]
scheduled = schedule_cells(cells, ScheduleOptions(schedule="npu-idle-min", schedule_report=report, jobs=4))
scheduled_idle = simulate_npu_idle(scheduled, report, jobs=4)
names = [item.example.rel_path for item in scheduled]
self.assertLessEqual(scheduled_idle, 58.0)
self.assertLess(names.index("fast-a"), names.index("slow-b"))
def test_npu_idle_min_prefers_lower_makespan_after_idle(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
report = root / "report.json"
write_timing_report(
report,
{
"long-build": (100, 1),
"long-run-a": (1, 80),
"long-run-b": (1, 70),
"short-run": (1, 1),
},
)
cells = [cell(root, name) for name in ["short-run", "long-run-a", "long-build", "long-run-b"]]
scheduled = schedule_cells(cells, ScheduleOptions(schedule="npu-idle-min", schedule_report=report, jobs=3))
build_desc = schedule_cells(cells, ScheduleOptions(schedule="build-desc", schedule_report=report, jobs=3))
scheduled_idle = simulate_npu_idle(scheduled, report, jobs=3)
build_desc_idle = simulate_npu_idle(build_desc, report, jobs=3)
scheduled_makespan = simulate_npu_makespan(scheduled, report, jobs=3)
build_desc_makespan = simulate_npu_makespan(build_desc, report, jobs=3)
self.assertLessEqual(scheduled_idle, build_desc_idle)
self.assertLessEqual(scheduled_makespan, build_desc_makespan)
if __name__ == "__main__":
unittest.main()