File size: 3,275 Bytes
77e087f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | # SPDX-FileCopyrightText: © 2026 Tenstorrent Inc.
# SPDX-License-Identifier: Apache-2.0
"""Device test: the FIRST real call after ``HamerModel.from_pretrained`` runs at the steady speed (warm-up), and the
warm-up does not change any output.
Each case runs ``code/scripts/first_call.py`` in a FRESH process (one chip as device 0, the released weights in the HF
cache): ``from_pretrained``, then 30 real calls with new inputs (the demo hands; never the warm-up input).
- ``test_first_call_fast[variant]``: call 1 <= FIRST_CALL_TOL x the median of the later calls on the same demo hand
(calls 9, 17, 25; the crop size, and so the host time, depends on the hand). Before the warm-up API call 1 was
1.29-1.55x for a JPEG file (right / left hand), after it 0.99-1.06x; see PYTHON.md "Warm-up".
- ``test_warmup_does_not_change_outputs``: the 30 outputs of ``warmup_variants="default"`` and ``"none"`` are bit-identical.
source tools/chipenv.sh $CHIP models/hamer-p150/.venv
cd models/hamer-p150 && timeout -s INT 900 python -m pytest code/tests/test_first_call_device.py -q -s
"""
from __future__ import annotations
import json
import os
import subprocess
import sys
from pathlib import Path
import pytest
if os.environ.get("TT_VISIBLE_DEVICES") == "none" or os.environ.get("HAMER_USE_TT") == "0":
pytest.skip("device test (TT_VISIBLE_DEVICES=none / HAMER_USE_TT=0)", allow_module_level=True)
import numpy as np # noqa: E402
REPO = Path(__file__).resolve().parents[2]
SCRIPT = REPO / "code" / "scripts" / "first_call.py"
# The residual is the cost of the first call after ANY idle gap (cold CPU caches), measured at 1.04-1.13x on the same
# hosts in a warm process (first_call.py "after_idle"); the tolerance leaves room for host-load noise on a shared host.
FIRST_CALL_TOL = float(os.environ.get("HAMER_FIRST_CALL_TOL", "1.20"))
def _run(variant: str, out: Path, warmup="default") -> dict:
cmd = [sys.executable, str(SCRIPT), "--variant", variant, "--out", str(out),
"--kwargs", json.dumps({"warmup_variants": warmup})]
r = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
assert r.returncode == 0, r.stdout[-3000:] + r.stderr[-3000:]
return json.loads((out / f"{variant}.json").read_text())
@pytest.mark.parametrize("variant", ["right", "left", "run_crop"])
def test_first_call_fast(variant, tmp_path):
res = _run(variant, tmp_path)
print(f"\n[first_call] {variant}: from_pretrained {res['from_pretrained_s']} s, call1 {res['call1_ms']} ms, "
f"call2 {res['call2_ms']} ms, call10 {res['call10_ms']} ms, steady {res['steady_median_ms']} ms, "
f"same-hand {res['same_input_median_ms']} ms, after idle {res['after_idle_ms']} ms")
assert res["warmup_variants"], "from_pretrained did not record its warm-up variants"
assert res["call1_over_same_input"] <= FIRST_CALL_TOL, res
def test_warmup_does_not_change_outputs(tmp_path):
a, b = tmp_path / "default", tmp_path / "none"
_run("right", a, "default")
res = _run("right", b, None)
assert res["warmup_variants"] == []
za, zb = np.load(a / "right.npz"), np.load(b / "right.npz")
assert za.files == zb.files and len(za.files) == 30
for k in za.files:
assert np.array_equal(za[k], zb[k]), k
|