AsianPlayer/TriDrive / code /baselines_dms /run_full_extraction.py
AsianPlayer's picture
download
raw
71.9 kB
#!/usr/bin/env python3
"""cwm3/baselines_dms/run_full_extraction.py — ONE shared native decode per route feeding every extractor of a model set (full-exposure DMS-baseline extraction, 2026-09-14).
Why layer 1 trains the U-base on ALL TRAIN rows and layer 3 needs alerts/h over the whole test exposure, so every baseline needs per-frame features on the entire
s12 5 Hz grid of every route (local cabin video: 5.84 M frames @ 10 Hz over the merged [t-8.2, t+0.2] spans of 1,066 routes). Six independent extractors
(each with its own decode; Phase 1 measured 22.6-31.2 ms per native frame per worker) would cost ~300 h; here a route is decoded ONCE per model set and
every decoded frame is handed to every selected model.
Sets --models cpu = ov_gaze, ov_action, mp_face (openvino / mediapipe, 4 threads each, inferred one after the other in the main process)
--models gpu = openface3, l2cs_gaze, videomae2 (cuda:0; with --l2cs-detector shared RetinaFace runs ONCE per frame: openface3.detect_faces -> the same box
goes to openface3.infer(dets=...) and l2cs_gaze.infer_with_boxes, L2CS's own face cut / resize / gaze transform unchanged)
Frames per (tier, route): the union over the route's anchors of [t - 8.2, t + 0.2] (video_io.spans_from_anchors, merged — the s12 rows are 0.2 s apart but the packs
have gaps, so a route has several spans) on the 10 Hz frame/20 grid. Window models add a causal lead-in so that every 5 Hz window inside the spans is
complete: videomae2 3.0 s (videomae2.lead_in_spans, as in Phase 1), ov_action 1.5 s (15 frames at 10 Hz; Phase 1 had none -> its first 7 windows per span were
invalid by construction). The decode covers the union; each model consumes only the frames inside its own spans (per-frame models never see the lead-in).
Decode video_io.FrameStream / decode_block (index-exact, native resolution, `workers` spawn processes with 2 ffmpeg threads, blocks of `block` frames, box in native
px). A model with a decode_wh (ov_action 960x600; videomae2 aspect-preserving 600 px) gets cv2.resize(native, INTER_AREA) of the SAME frame = exactly what
decode_block did for it in Phase 1, and the driver box scaled exactly as FrameStream.box_for_frame; the crop is video_io.driver_crop (+10 %) in every case.
Batches are flushed at every contiguous-span end (Phase 1 ran run_route once per span for openface3 / ov_action), so batch compositions match Phase 1.
Caches results/baselines_dms/cache/<b>/<uid>.npz — cache_schema.RouteCache with the Phase-1 channels / meta keys plus shared_decode, model_set, face_detector,
lead_in_s, tier, requested_spans; window caches results/baselines_dms/cache/<b>/windows/<uid>.npz (ov_action: OvActionExtractor.decode_windows over the per-frame
embeddings, 16 frames at 10 Hz ending at every 5 Hz step; videomae2: WindowAssembler, 16 frames at 5 Hz). summarise.write_summary reads them unchanged
(cache_dir = cs.cache_dir(b), window_dir = cs.cache_dir(b) / "windows").
Resume a route whose caches already cover the requested spans is skipped; a partial cache (time budget / kill / --checkpoint-frames) is written as <uid>.part.npz
(+ windows/<uid>.part.npz; spans truncated at the last decoded frame) and EXTENDED on the next run — only the uncovered spans are decoded
(cache_schema.spans_subtract; videomae2 re-decodes the 3.0 s lead-in before each resumed span so its clips are complete) and merged (RouteCache.merged_with).
The complete file is written and the .part removed only when the cache covers the request, so summarise.py never sees a partial cache under <uid>.npz.
Queue results/baselines_dms/full/route_queue.csv (written before the first route; --build-queue rewrites it): tier A = the anchor windows of the routes carrying the
979 TRAIN label anchors (data.labels.train_label_table), the clean gold anchors (warning_gold.build_gold, clean_test + clean_val) and the newtest manifest
clips (small -> layer 2 first); tier B = val exposure; tier C = test exposure; tier D = train exposure (tier-A routes reappear there and are EXTENDED).
results/baselines_dms/full/progress.json holds one record per set (routes / frames done per tier, rolling fps, ETA per tier), rewritten after every route.
Exit 0 = every queued route complete for the selected models; 3 = --max-minutes reached with work remaining (relaunch); 4 = a route failed (the others are done);
5 = resources not available at start (GPU gate / RAM). Guards before every route: MemAvailable >= 28 GB and 1-min load < 21 (waits, never kills anything).
Sharding (2026-09-15) two processes of the SAME model set may walk the queue concurrently: (i) every cache write is atomic (cache_schema.savez_atomic: tmp + os.replace),
(ii) a route is CLAIMED before it is processed (<cache>/<first model>/<uid>.claim, O_EXCL, json pid / utc / tag; removed in finally; a claim whose pid is dead is
taken over) and a route claimed by a live other pid is deferred (status claimed_by_other), (iii) with --skip-fresh-part-min M a route whose .part.npz was written
by another tag within the last M minutes is deferred too (status in_progress_elsewhere: a process that predates the claim files is working on it),
(iv) --reverse walks the filtered queue from the end so that two shards meet in the middle. Deferred routes are re-polled (every 120 s) after the queue until they
exist or the budget ends; they count as remaining (exit 3) when still held. Without the new flags and with a single process nothing changes.
python baselines_dms/run_full_extraction.py --build-queue
python baselines_dms/run_full_extraction.py --models cpu --workers 4 --max-minutes 600 [--tiers A,B,C,D] [--uids u1,u2] [--out-root DIR] [--limit-frames N]
python baselines_dms/run_full_extraction.py --models gpu --l2cs-detector shared|own --workers 4 --max-minutes 600
python baselines_dms/run_full_extraction.py --models cpu --workers 3 --reverse --tiers C,D --tag cpu_shard2 --max-load1 19 --skip-fresh-part-min 20 # second shard
python baselines_dms/run_full_extraction.py --verify-phase1 --models cpu|gpu --uids u1,u2,u3 # manifest windows -> full/verify_phase1/, per-model max |diff| vs phase1 caches
python baselines_dms/run_full_extraction.py --l2cs-detector-check # 45 Phase-1 routes: shared RetinaFace box vs the package detector (rho / median |d|)
No openpilot field is read; no network; nothing here trains or tunes anything.
"""
from __future__ import annotations
import argparse
import contextlib
import csv
import fcntl
import importlib
import json
import os
import sys
import time
from pathlib import Path
import numpy as np
os.environ.setdefault("OMP_NUM_THREADS", "4")
os.environ.setdefault("MKL_NUM_THREADS", "4")
PKG = Path(__file__).resolve().parent
CWM3 = PKG.parent
EXT = PKG / "extractors"
for _p in (str(CWM3), str(PKG), str(EXT)):
if _p not in sys.path:
sys.path.insert(0, _p)
import cache_schema as cs # noqa: E402
import video_io as vio # noqa: E402
import base as B # noqa: E402 (extractors/base.py: fail_codes_for, exit codes)
FULL_DIR = cs.RESULTS_ROOT / "full"
QUEUE_CSV = FULL_DIR / "route_queue.csv"
PROGRESS_JSON = FULL_DIR / "progress.json"
PHASE1 = cs.RESULTS_ROOT / "phase1"
MANIFEST = PHASE1 / "manifest_v1.csv"
NEWTEST_MANIFEST = CWM3 / "results" / "newtest" / "manifest_v1.csv"
SETS = {"cpu": ("ov_gaze", "ov_action", "mp_face"), "gpu": ("openface3", "l2cs_gaze", "videomae2")}
ALL_MODELS = SETS["cpu"] + SETS["gpu"]
WINDOW_MODELS = ("ov_action", "videomae2")
LEAD_IN_S = {"ov_action": 1.5, "videomae2": 3.0}
TIER_PACKS = {"B": ("manual_val", "engaged_val"), "C": ("manual_test", "engaged_test"), "D": ("manual_train", "engaged_train")}
TIERS = ("A", "B", "C", "D")
EXIT_DONE, EXIT_BUDGET, EXIT_FAIL, EXIT_RESOURCES = B.EXIT_DONE, B.EXIT_BUDGET, B.EXIT_FAIL, 5
NEED_RAM_GB, MAX_LOAD1, VRAM_HEADROOM_GB = 28.0, 21.0, 4.0
DEFER_POLL_S = 120.0 # re-poll interval for routes deferred to another process
NEED_VRAM_GB = {"openface3": 2.0, "l2cs_gaze": 3.0, "videomae2": 2.5}
PHASE1_WINDOW_DIR = {"ov_action": "cache_win", "videomae2": "windows"}
FACE_DETECTOR = {"openface3": "openface3 RetinaFace mnet0.25 (Alignment_RetinaFace.pth sha256 2979b33f...; top-scoring anchor, score >= 0.5)",
"l2cs_own": "own: face_detection package RetinaFace mnet0.25 (mobilenet0.25_Final.pth, byte-identical weights; NMS, largest box, score >= 0.5)",
"l2cs_shared": "shared: openface3.detect_faces box (top-scoring anchor, score >= 0.5) -> L2CS face_crop (int bounds, clip 0, BGR->RGB, 224x224)",
"ov_gaze": "omz face-detection-adas-0001 (fd_mode reshape, conf >= 0.5)", "mp_face": "mediapipe BlazeFace short-range (Face Landmarker task)",
"ov_action": "none (driver crop)", "videomae2": "none (driver crop)"}
# ----------------------------------------------------------------------------- resources
def mem_available_gb():
for line in open("/proc/meminfo"):
if line.startswith("MemAvailable"):
return int(line.split()[1]) / 2**20
return float("nan")
def load1():
return float(open("/proc/loadavg").read().split()[0])
def gpu_free_gb():
import subprocess
try:
s = subprocess.run(["nvidia-smi", "--query-gpu=memory.free", "--format=csv,noheader,nounits"], capture_output=True, text=True, timeout=20).stdout
return float(s.strip().splitlines()[0]) / 1024.0
except Exception:
return float("nan")
def wait_for_resources(deadline, log=print, need_ram=NEED_RAM_GB, max_load=MAX_LOAD1, poll_s=60):
"""block (never kill anything) until MemAvailable >= need_ram GB and the 1-min load < max_load, or the deadline passes; -> True when the resources are there."""
waited = False
while time.time() < deadline:
ram, ld = mem_available_gb(), load1()
if ram >= need_ram and ld < max_load:
return True
if not waited:
log(f"waiting for resources: MemAvailable {ram:.1f} GB (need {need_ram}), load1 {ld:.1f} (max {max_load})")
waited = True
time.sleep(poll_s)
return False
# ----------------------------------------------------------------------------- queue
def tier_a_anchors(log=print):
"""-> ({uid: sorted f64 anchor times}, {uid: [sources]}, counts) over the 979 TRAIN label anchors, the clean gold anchors and the newtest manifest clips."""
import pandas as pd
vio._shim_labels()
from data.labels import train_label_table
import warning_gold as WG
A, src = {}, {}
def add(uids, ts, tag):
for u, t in zip(uids, ts):
A.setdefault(str(u), []).append(float(t))
src.setdefault(str(u), set()).add(tag)
T = train_label_table(("consensus",))
add(T.uid, T.t_anchor, "train979")
EP = WG.episode_table()
lab = EP[EP.label != "unsure"].reset_index(drop=True)
packs = {(r, s): WG.load_pack(r, s) for r in ("manual", "engaged") for s in ("test", "val")}
Gs = []
for seed in (0, 1, 2):
legacy = WG.merge_legacy(seed)
if legacy is not None:
Gs.append(WG.build_gold(lab, packs, legacy, "legacy_first"))
Gs.append(WG.build_gold(lab, packs, None, "s12"))
GA = pd.concat(Gs, ignore_index=True)
GA = GA[GA.clean_test | GA.clean_val]
E = GA.drop_duplicates(["uid", "t_anchor"])
add(E.uid, E.t_anchor, "gold")
M = pd.read_csv(NEWTEST_MANIFEST)
add(M.uid, M.t_anchor, "newtest")
counts = {"train979_rows": int(len(T)), "gold_rows_clean_test": int(GA[GA.clean_test].drop_duplicates("idx").shape[0]), "gold_rows_clean_val": int(GA[GA.clean_val].drop_duplicates("idx").shape[0]),
"gold_uid_t_unique": int(len(E)), "newtest_rows": int(len(M)), "newtest_uids": int(M.uid.nunique())}
log(f"tier A anchors: {json.dumps(counts)}")
return {u: np.unique(np.asarray(v, np.float64)) for u, v in A.items()}, {u: sorted(s) for u, s in src.items()}, counts
def route_row(tier, uid, ts, sources):
has = vio.has_video(uid)
n_video = 0
if has:
try:
n_video = int(vio.video_info(vio.video_path(uid))[2])
except Exception:
has = False
sp = vio.spans_from_anchors(ts, vio.HIST_S, vio.POST_S)
k = vio.frames_in_spans(sp, cs.HZ, n_video if has else None)[0]
return {"tier": tier, "uid": uid, "sources": "+".join(sources), "n_anchor_rows": int(len(ts)), "n_spans": int(len(sp)), "span_s": round(float(np.sum(sp[:, 1] - sp[:, 0])), 1),
"n_frames10": int(len(k)), "video_local": int(has), "pose_cache": int(vio.pose_path(uid) is not None), "n_video_frames": n_video,
"spans": json.dumps(np.round(sp.astype(np.float64), 3).tolist())}
def build_queue(path=QUEUE_CSV, log=print):
"""write the ordered (tier, route) queue; tier A sorted by frame count (smallest first), tiers B-D by uid. -> list of rows."""
t0 = time.time()
A, src, counts = tier_a_anchors(log)
rows = [route_row("A", u, A[u], src[u]) for u in sorted(A)]
rows.sort(key=lambda r: (r["n_frames10"], r["uid"]))
for tier, packs in TIER_PACKS.items():
AB = vio.anchors_by_uid(packs)
per = {p: set(vio.anchors_by_uid((p,))) for p in packs}
rows += [route_row(tier, u, AB[u], [p for p in packs if u in per[p]]) for u in sorted(AB)]
for i, r in enumerate(rows):
r["order"] = i
path.parent.mkdir(parents=True, exist_ok=True)
cols = ["order", "tier", "uid", "sources", "n_anchor_rows", "n_spans", "span_s", "n_frames10", "video_local", "pose_cache", "n_video_frames", "spans"]
with open(path, "w", newline="") as f:
w = csv.DictWriter(f, fieldnames=cols)
w.writeheader()
for r in rows:
w.writerow({c: r[c] for c in cols})
summ = queue_summary(rows)
summ.update(anchor_counts=counts, written_utc=time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), wall_s=round(time.time() - t0, 1), path=str(path))
(path.with_suffix(".json")).write_text(json.dumps(summ, indent=1))
log(f"queue: {json.dumps(summ['tiers'])}")
return rows
def queue_summary(rows):
out = {"tiers": {}}
for tier in TIERS:
rr = [r for r in rows if r["tier"] == tier]
loc = [r for r in rr if int(r["video_local"])]
out["tiers"][tier] = {"routes": len(rr), "routes_local": len(loc), "frames10_local": int(sum(int(r["n_frames10"]) for r in loc)),
"frames10_all": int(sum(int(r["n_frames10"]) for r in rr)), "anchor_rows": int(sum(int(r["n_anchor_rows"]) for r in rr)),
"hours_local": round(sum(int(r["n_frames10"]) for r in loc) / 36000.0, 2)}
out["routes_local_unique"] = len({r["uid"] for r in rows if int(r["video_local"])})
out["frames10_local_total"] = int(sum(v["frames10_local"] for v in out["tiers"].values()))
return out
def load_queue(path=QUEUE_CSV):
with open(path) as f:
rows = list(csv.DictReader(f))
for r in rows:
for k in ("order", "n_anchor_rows", "n_spans", "n_frames10", "video_local", "pose_cache", "n_video_frames"):
r[k] = int(r[k])
r["span_s"] = float(r["span_s"])
r["spans_arr"] = np.asarray(json.loads(r["spans"]), np.float64).reshape(-1, 2)
return rows
# ----------------------------------------------------------------------------- progress
def update_progress(set_name, record, path=PROGRESS_JSON):
"""read-modify-write of the per-set progress record under a file lock (the cpu and gpu runners share the file)."""
path.parent.mkdir(parents=True, exist_ok=True)
lock = path.with_suffix(".lock")
with open(lock, "w") as lf:
fcntl.flock(lf, fcntl.LOCK_EX)
try:
P = json.loads(path.read_text()) if path.exists() else {}
except Exception:
P = {}
P[set_name] = record
P["updated_utc"] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
tmp = path.with_suffix(".tmp")
tmp.write_text(json.dumps(P, indent=1, default=str))
os.replace(tmp, path)
fcntl.flock(lf, fcntl.LOCK_UN)
# ----------------------------------------------------------------------------- model slots
def scaled_box(b, W, H, dw, dh):
"""the driver box in the coordinates of a frame resized from (W, H) to (dw, dh) — the same expression as video_io.FrameStream.box_for_frame (box_coords 'frame')."""
if np.isfinite(b).all():
sx, sy = dw / W, dh / H
return np.array([b[0] * sx, b[1] * sy, b[2] * sx, b[3] * sy], np.float32)
return b.copy()
class Slot:
"""one model of the set: the Phase-1 extractor (setup unchanged), its cache directories, decode size and detector convention."""
def __init__(self, name, device="cuda:0", out_root=cs.RESULTS_ROOT, l2cs_detector="own"):
assert name in ALL_MODELS, name
self.name, self.device = name, device
self.mod = importlib.import_module(name)
self.cache_dir = cs.cache_dir(name, out_root)
self.win_dir = self.cache_dir / "windows"
self.is_window = name in WINDOW_MODELS
self.lead_in = LEAD_IN_S.get(name, 0.0)
self.l2cs_detector = l2cs_detector if name == "l2cs_gaze" else None
self.ex = None
def setup(self, log=print):
t0 = time.time()
m, n = self.mod, self.name
if n == "ov_gaze":
self.ex = m.make_extractor("reshape")
elif n == "mp_face":
self.ex = m.MPFaceExtractor().setup()
elif n == "ov_action":
self.ex = m.OvActionExtractor(n_threads=4).setup(None)
elif n == "openface3":
self.ex = m.OpenFace3Extractor(self.device).setup()
elif n == "l2cs_gaze":
self.ex = m.L2CSGazeExtractor().setup(device=self.device)
elif n == "videomae2":
self.ex = m.VideoMAE2Extractor().setup(device=self.device)
self.batch = int(self.ex.batch)
log(f"[{n}] setup {time.time() - t0:.1f}s; channels {self.ex.C}; batch {self.batch}; decode_wh {self.ex.decode_wh}; detector {self.face_detector()}")
return self
@property
def channels(self):
return list(self.ex.channels)
def decode_wh_for(self, native_wh):
if self.name == "videomae2":
return tuple(self.mod.decode_wh_for(native_wh))
return None if self.ex.decode_wh is None else tuple(int(v) for v in self.ex.decode_wh)
def face_detector(self):
if self.name == "l2cs_gaze":
return FACE_DETECTOR["l2cs_shared" if self.l2cs_detector == "shared" else "l2cs_own"]
return FACE_DETECTOR[self.name]
def code_sha(self):
return cs.code_sha256(list(self.ex.code_files()) + [Path(__file__)])
def plan_job(name, req_spans, have_rc_spans, have_wc_spans, n_video, mod=None):
"""pure planning of one model on one route -> dict(rc_req, wc_req, todo_rc, todo_dec, k5, windows_complete). req_spans = the route's anchor spans; have_* = spans of the
existing (possibly partial) caches or None. Window models: rc_req adds the causal lead-in; todo_dec adds the lead-in before every window span still to compute
(videomae2: the clip needs the 15 earlier 5 Hz frames, so a resumed span re-decodes 3.0 s)."""
req = cs.merge_spans(req_spans)
if name == "videomae2":
mod = mod or importlib.import_module("videomae2")
rc_req = cs.merge_spans(mod.lead_in_spans(req, n_video, True)) if len(req) else req
wc_req = req
elif name == "ov_action":
rc_req = cs.merge_spans([[max(0.0, a - LEAD_IN_S["ov_action"]), b] for a, b in req.astype(np.float64)]) if len(req) else req
wc_req = req
else:
rc_req, wc_req = req, None
todo_rc = rc_req if have_rc_spans is None else cs.spans_subtract(rc_req, have_rc_spans)
todo_dec, k5, windows_complete = todo_rc, None, True
if name == "videomae2":
wc_todo = wc_req if have_wc_spans is None else cs.spans_subtract(wc_req, have_wc_spans)
k5, _ = mod.window_grid(wc_todo, n_video)
windows_complete = len(k5) == 0
if len(k5):
todo_dec = cs.merge_spans(np.concatenate([todo_rc.reshape(-1, 2), np.asarray(mod.lead_in_spans(wc_todo, n_video, True), np.float32).reshape(-1, 2)]))
elif name == "ov_action":
windows_complete = have_wc_spans is not None and cs.spans_cover(have_wc_spans, wc_req)
return {"rc_req": rc_req, "wc_req": wc_req, "todo_rc": todo_rc, "todo_dec": todo_dec, "k5": k5, "windows_complete": windows_complete}
def merge_window_caches(old: cs.WindowCache, new: cs.WindowCache) -> cs.WindowCache:
"""union of two window caches of one route (rows of `new` win on a duplicate win_t_end); spans merged; meta / runtime of `new`."""
k = np.round(np.concatenate([old.win_t_end, new.win_t_end]).astype(np.float64) * cs.HZ).astype(np.int64)
order = np.argsort(k, kind="stable")
ks = k[order]
keep_last = np.r_[ks[1:] != ks[:-1], True]
sel = order[keep_last]
def cat(a, b):
return np.concatenate([a, b])[sel]
return cs.WindowCache(new.uid, cat(old.win_t_end, new.win_t_end), cat(old.emb, new.emb), cat(old.win_valid, new.win_valid), int(new.win_len),
cs.merge_spans(np.concatenate([old.spans, new.spans])), dict(new.meta), dict(new.runtime))
def _load_cache(p_full, p_part, cls, force, log):
"""the complete cache if present (unless force), else the partial one; unreadable -> None (rebuilt)."""
if force:
return None
for p in (p_full, p_part):
if p is not None and p.exists():
try:
return cls.load(p)
except Exception as e:
log(f"{p.name}: cannot read ({repr(e)[:80]}); recomputing")
return None
return None
class SlotJob:
"""per-route state of one model: the plan, the existing caches, the frame mask over the shared decode, the pending batch and the feature rows."""
def __init__(self, slot: Slot, uid, req_spans, n_video, native_wh, tier, force=False, log=print):
self.slot, self.uid, self.tier = slot, uid, tier
self.decode_wh = slot.decode_wh_for(native_wh)
self.native_wh = tuple(int(v) for v in native_wh)
self.p_rc, self.p_rc_part = slot.cache_dir / f"{uid}.npz", slot.cache_dir / f"{uid}.part.npz"
self.p_wc = slot.win_dir / f"{uid}.npz" if slot.is_window else None
self.p_wc_part = slot.win_dir / f"{uid}.part.npz" if slot.is_window else None
self.have = _load_cache(self.p_rc, self.p_rc_part, cs.RouteCache, force, log)
if self.have is not None and self.have.channels != slot.channels:
log(f"[{slot.name}] {uid[:40]}: existing cache channels differ; recomputing")
self.have = None
self.have_wc = _load_cache(self.p_wc, self.p_wc_part, cs.WindowCache, force, log) if slot.is_window else None
if self.have_wc is not None and (self.have is None or self.have_wc.D != (slot.ex.D if slot.name == "videomae2" else slot.mod.N_CLASSES)):
self.have_wc = None
plan = plan_job(slot.name, req_spans, None if self.have is None else self.have.spans, None if self.have_wc is None else self.have_wc.spans, n_video, slot.mod)
self.rc_req, self.wc_req, self.todo_dec, self.k5 = plan["rc_req"], plan["wc_req"], plan["todo_dec"], plan["k5"]
self.windows_complete = plan["windows_complete"]
self.needs_decode = len(self.todo_dec) > 0
self.needs_work = self.needs_decode or (slot.is_window and not self.windows_complete)
self.mask = None
self.asm = None
self.pend_idx, self.pend_crops, self.infer_ms = [], [], []
self.batch = slot.batch
def bind(self, fs):
N = len(fs.frame_idx)
kj = vio.frames_in_spans(self.todo_dec, cs.HZ, fs.n_frames)[0] if self.needs_decode else np.zeros(0, np.int64)
self.mask = np.isin(fs.k, kj)
self.feat = np.full((N, self.slot.ex.C), np.nan, np.float32)
self.had_frame = np.zeros(N, bool)
if self.slot.name == "videomae2" and self.k5 is not None and len(self.k5):
self.asm = self.slot.mod.WindowAssembler(self.slot.ex, self.k5)
def feed(self, i, k, fr, box_native, get_view):
"""one decoded frame -> crop for this model (only inside its own spans); -> True when the pending batch is full."""
if not self.mask[i]:
return False
crop = None
if fr is not None:
self.had_frame[i] = True
view, box_v = get_view(self.decode_wh)
crop = vio.driver_crop(view, box_v)
if crop is not None:
if self.slot.name == "videomae2": # per-frame channels = crop geometry (cheap, no model)
self.feat[i] = self.slot.ex.infer([crop])[0]
else:
self.pend_idx.append(i)
self.pend_crops.append(crop)
if self.asm is not None:
self.asm.feed(k, fr is not None, crop)
return len(self.pend_idx) >= self.batch
def store(self, rows):
assert rows.shape == (len(self.pend_idx), self.slot.ex.C), (rows.shape, len(self.pend_idx), self.slot.ex.C)
self.feat[np.asarray(self.pend_idx)] = rows
self.pend_idx.clear()
self.pend_crops.clear()
def flush_jobs(jobs, coupled, force_all=False):
"""run the pending batches: `coupled` = (openface3 job, l2cs job) sharing one RetinaFace pass (both pending lists are identical by construction)."""
of3, l2 = coupled if coupled else (None, None)
for j in jobs:
if not j.pend_idx or (not force_all and len(j.pend_idx) < j.batch):
continue
if j is l2 and of3 is not None:
continue # handled together with openface3 below
t0 = time.time()
if j is of3 and l2 is not None:
assert j.pend_idx == l2.pend_idx, "shared detector: openface3 / l2cs pending frames differ"
dets = j.slot.ex.detect_faces(j.pend_crops)
rows = j.slot.ex.infer(j.pend_crops, dets=dets)
n = len(j.pend_idx)
j.store(np.asarray(rows, np.float32).reshape(n, -1))
t1 = time.time()
rows2 = l2.slot.ex.infer_with_boxes(l2.pend_crops, dets)
l2.store(np.asarray(rows2, np.float32).reshape(n, -1))
j.infer_ms.append(1000.0 * (t1 - t0) / n)
l2.infer_ms.append(1000.0 * (time.time() - t1) / n)
continue
n = len(j.pend_idx)
rows = np.asarray(j.slot.ex.infer(j.pend_crops), np.float32).reshape(n, -1)
j.store(rows)
j.infer_ms.append(1000.0 * (time.time() - t0) / n)
def finalize_job(job: SlotJob, fs, n_done, partial, model_set, wall_s, log=print, tag=""):
"""rows so far -> RouteCache (+ WindowCache) merged with the existing cache; written as <uid>.npz when it covers the request, else <uid>.part.npz. -> info dict.
meta.writer_pid / writer_tag record the writing process (the fresh-.part rule of run_queue reads writer_tag)."""
slot, ex = job.slot, job.slot.ex
info = {"model": slot.name}
if job.needs_decode:
rows_idx = np.flatnonzero(job.mask[:n_done])
feat = job.feat[rows_idx].copy()
had_frame = job.had_frame[rows_idx]
had_box = np.isfinite(fs.box[rows_idx]).all(1)
fail = B.fail_codes_for(feat, had_frame, had_box, True)
valid = fail == 0
feat[~valid] = np.nan
if partial:
t_last = float(fs.t[n_done - 1]) if n_done else float(job.todo_dec[0, 0]) - 1.0
done_spans = np.array([[a, min(b, t_last)] for a, b in job.todo_dec.astype(np.float64) if a <= t_last], np.float32).reshape(-1, 2)
else:
done_spans = job.todo_dec
extra = dict(pose_source=(fs.boxes or {}).get("source", "none"), needs_crop=True, crop_expand=vio.MARGIN, hz=cs.HZ, partial=bool(partial), video_path=str(fs.vpath),
n_video_frames=int(fs.n_frames), registry_entry=getattr(ex, "registry_entry", None), shared_decode=True, runner="baselines_dms/run_full_extraction.py",
model_set=list(model_set), face_detector=slot.face_detector(), lead_in_s=float(slot.lead_in), tier=job.tier, requested_spans=np.round(job.rc_req.astype(np.float64), 3).tolist(),
writer_pid=os.getpid(), writer_tag=str(tag or ""), **fs.decode_meta())
if slot.name == "videomae2":
m = slot.mod
extra.update(decode_h=m.DECODE_H, letterbox=f"long side -> {m.IMG}, centred, pad RGB {m.PAD_RGB}", colour="BGR->RGB, /255, ImageNet mean {} std {}".format(m.MEAN_RGB, m.STD_RGB),
win_len=m.L, win_hz=m.WIN_HZ, win_span_s=m.WIN_SPAN_S, frame_stride_10hz=m.STEP10, emb_dim=ex.D, feature="forward_features = fc_norm(mean over tokens), pre-logit, fp16",
n_params=getattr(ex, "n_params", None), win_fail_codes=m.WIN_FAIL, channel_roles=ex.spec())
meta = cs.make_meta(ex.baseline, ex.model_ids, ex.weight_sha256, ex.lib_versions, job.decode_wh or job.native_wh, job.native_wh, slot.code_sha(), "local", **extra)
runtime = cs.make_runtime(fs.stats["decode_ms_per_frame"], job.infer_ms, len(rows_idx), wall_s=wall_s)
new = cs.RouteCache(job.uid, fs.t[rows_idx].astype(np.float32), fs.frame_idx[rows_idx].astype(np.int64), fs.box[rows_idx].astype(np.float32), valid, fail,
feat.astype(np.float16), slot.channels, cs.merge_spans(done_spans), meta, runtime, moving=fs.moving[rows_idx].astype(bool))
if job.have is not None and job.have.n:
new = job.have.merged_with(new)
new.meta["resumed_from_partial"] = True
rc = new
else:
rc = job.have
complete = rc is not None and rc.covers(job.rc_req)
rc.meta["partial"] = not complete
info.update(n_rows=int(rc.n), n_new_rows=int(len(np.flatnonzero(job.mask[:n_done]))) if job.needs_decode else 0, valid_rate=float(rc.valid.mean()) if rc.n else None,
fail_hist={cs.FAIL_CODES[int(a)]: int(b) for a, b in zip(*np.unique(rc.fail, return_counts=True))}, complete=bool(complete))
# ---- windows
wc, wc_complete = None, True
if slot.name == "ov_action":
if complete:
wc = ex.decode_windows(rc, job.wc_req)
wc.meta.update(shared_decode=True, lead_in_s=float(slot.lead_in), tier=job.tier)
else:
wc_complete = False # rebuilt from the complete per-frame cache at the end
elif slot.name == "videomae2":
if job.asm is not None:
emb, wv, wf, infer_ms, pre_ms = job.asm.finish()
m = slot.mod
k_last = int(fs.k[n_done - 1]) if (partial and n_done) else None
sel = np.ones(len(job.k5), bool) if k_last is None else (job.k5 * m.STEP10 <= k_last)
t_end = (job.k5[sel] / m.WIN_HZ).astype(np.float32)
emb_s = emb[sel].astype(np.float16)
wc_spans = job.wc_req if (job.have_wc is None) else cs.spans_subtract(job.wc_req, job.have_wc.spans)
if k_last is not None:
t_l = k_last / cs.HZ
wc_spans = np.array([[a, min(b, t_l)] for a, b in wc_spans.astype(np.float64) if a <= t_l], np.float32).reshape(-1, 2)
rt = cs.make_runtime(fs.stats["decode_ms_per_frame"], infer_ms, len(np.flatnonzero(job.mask[:n_done])), wall_s=wall_s)
wfail = {m.WIN_FAIL.get(int(a), str(int(a))): int(b) for a, b in zip(*np.unique(wf[sel], return_counts=True))}
rt.update(infer_unit="window (ms per 16-frame window, batched)", n_windows=int(sel.sum()), n_windows_valid=int(wv[sel].sum()), batch=int(ex.batch),
preprocess_ms_p50=float(np.percentile(pre_ms, 50)) if pre_ms else float("nan"), preprocess_ms_p95=float(np.percentile(pre_ms, 95)) if pre_ms else float("nan"), win_fail_hist=wfail)
wc = cs.WindowCache(job.uid, t_end, emb_s, wv[sel].astype(bool), m.L, cs.merge_spans(wc_spans) if len(wc_spans) else np.zeros((0, 2), np.float32), dict(rc.meta, cache_kind="windows"), rt)
if job.have_wc is not None and job.have_wc.m:
wc = merge_window_caches(job.have_wc, wc)
else:
wc = job.have_wc
wc_complete = wc is not None and wc.covers(job.wc_req)
if wc is not None:
wc.meta["partial"] = not wc_complete
# ---- write
all_complete = complete and wc_complete
if all_complete:
rc.save(job.p_rc)
with contextlib.suppress(FileNotFoundError): # another process may have removed it first
job.p_rc_part.unlink()
if wc is not None:
wc.save(job.p_wc)
with contextlib.suppress(FileNotFoundError):
job.p_wc_part.unlink()
else:
if job.needs_decode:
rc.save(job.p_rc_part)
if wc is not None and slot.name == "videomae2":
wc.save(job.p_wc_part)
info.update(windows=(None if wc is None else int(wc.m)), windows_valid=(None if wc is None else int(wc.win_valid.sum())), status=("done" if all_complete else "partial"))
return info
def process_route(slots, uid, req_spans, tier, workers, block, deadline, model_set, l2cs_shared=False, force=False, limit_frames=0, checkpoint_frames=0, log=print, tag=""):
"""decode the route ONCE over the union of what the selected models still need and feed every frame to them. -> (code, info)."""
t_route = time.time()
info = {"uid": uid, "tier": tier, "status": "", "n_frames_decoded": 0, "wall_s": 0.0, "models": {}}
try:
vp = vio.video_path(uid)
W, H, n_video = vio.video_info(vp)
except (FileNotFoundError, RuntimeError) as e:
info.update(status="no_video", error=str(e))
return EXIT_FAIL, info
jobs = [SlotJob(s, uid, req_spans, n_video, (W, H), tier, force=force, log=log) for s in slots]
work = [j for j in jobs if j.needs_work]
if not work:
info.update(status="exists", wall_s=round(time.time() - t_route, 2))
return EXIT_DONE, info
coupled = None
if l2cs_shared: # one RetinaFace pass for both: the two jobs must see the SAME frames (union of what either still needs)
of3 = next((j for j in jobs if j.slot.name == "openface3"), None)
l2 = next((j for j in jobs if j.slot.name == "l2cs_gaze"), None)
if of3 is not None and l2 is not None and l2.needs_decode:
both = cs.merge_spans(np.concatenate([of3.todo_dec.reshape(-1, 2), l2.todo_dec.reshape(-1, 2)]))
of3.todo_dec, l2.todo_dec = both, both
of3.needs_decode = of3.needs_work = True
l2.batch = of3.batch
coupled = (of3, l2)
work = [j for j in jobs if j.needs_work]
dec = [j for j in jobs if j.needs_decode]
if not dec: # only windows to rebuild from complete per-frame caches (ov_action)
for j in work:
if j.slot.name == "ov_action":
info["models"][j.slot.name] = _rebuild_windows_only(j, log)
info.update(status="done", wall_s=round(time.time() - t_route, 2))
return EXIT_DONE, info
todo_all = cs.merge_spans(np.concatenate([j.todo_dec.reshape(-1, 2) for j in dec]))
try:
fs = vio.FrameStream(uid, todo_all, hz=cs.HZ, workers=workers, decode_wh=None, block=block, box_coords="native")
except FileNotFoundError as e:
info.update(status="no_video", error=str(e))
return EXIT_FAIL, info
for j in dec:
j.bind(fs)
N = len(fs.frame_idx)
if N == 0:
for j in work:
info["models"][j.slot.name] = finalize_job(j, fs, 0, False, model_set, time.time() - t_route, log, tag=tag)
info.update(status="done", n_frames_decoded=0, wall_s=round(time.time() - t_route, 2))
return EXIT_DONE, info
import cv2
budget_hit = False
it = iter(fs)
i = n_done = 0
prev_k = None
last_ckpt = 0
for t_, fi_, fr_, bx_ in it:
k = int(fs.k[i])
if prev_k is not None and k - prev_k > 1:
flush_jobs(dec, coupled, force_all=True) # contiguous-span end: Phase 1 ran one run_route per span
views = {}
def get_view(wh):
if wh is None or (wh[0] == W and wh[1] == H):
return fr_, bx_
if wh not in views:
views[wh] = (cv2.resize(fr_, (int(wh[0]), int(wh[1])), interpolation=cv2.INTER_AREA), scaled_box(bx_, W, H, wh[0], wh[1]))
return views[wh]
need_flush = False
for j in dec:
if j.feed(i, k, fr_, bx_, get_view):
need_flush = True
if need_flush:
flush_jobs(dec, coupled)
prev_k = k
i += 1
n_done = i
if i % block == 0 and i < N:
if time.time() > deadline or (limit_frames and i >= limit_frames):
budget_hit = True
break
if checkpoint_frames and i - last_ckpt >= checkpoint_frames:
flush_jobs(dec, coupled, force_all=True)
for j in work:
finalize_job(j, fs, i, True, model_set, time.time() - t_route, log, tag=tag)
last_ckpt = i
log(f" checkpoint {uid[:40]} {i}/{N} frames")
flush_jobs(dec, coupled, force_all=True)
if budget_hit:
it.close()
for j in work:
info["models"][j.slot.name] = finalize_job(j, fs, n_done, budget_hit, model_set, time.time() - t_route, log, tag=tag)
wall = time.time() - t_route
info.update(status=("budget" if budget_hit else "done"), n_frames_decoded=int(n_done), n_frames_requested=int(N), wall_s=round(wall, 2), fps=round(n_done / max(wall, 1e-9), 2),
decode_worker_fps=round(fs.stats["n_grab"] / max(fs.stats["decode_worker_s"], 1e-9), 1), decode_ms_p50=float(np.median(fs.stats["decode_ms_per_frame"])) if fs.stats["decode_ms_per_frame"] else None,
decode_meta=fs.decode_meta(), spans_decoded=np.round(todo_all.astype(np.float64), 2).tolist()[:8])
return (EXIT_BUDGET if budget_hit else EXIT_DONE), info
def _rebuild_windows_only(job: SlotJob, log=print):
"""ov_action: complete per-frame cache but no (complete) window cache -> decode_windows without any decode."""
assert job.slot.name == "ov_action" and job.have is not None
wc = job.slot.ex.decode_windows(job.have, job.wc_req)
wc.meta.update(shared_decode=True, lead_in_s=float(job.slot.lead_in), tier=job.tier)
wc.save(job.p_wc)
with contextlib.suppress(FileNotFoundError):
job.p_wc_part.unlink()
return {"model": job.slot.name, "status": "done", "windows_rebuilt": int(wc.m), "windows_valid": int(wc.win_valid.sum()), "complete": True}
# ----------------------------------------------------------------------------- claims (two shards of one model set)
def pid_alive(pid):
try:
os.kill(int(pid), 0)
except ProcessLookupError:
return False
except PermissionError:
return True
except (TypeError, ValueError, OverflowError):
return False
return True
def claim_path(slots, uid):
"""<cache>/<first model of the set>/<uid>.claim — one claim per (model set, route); the GPU set has its own cache dirs, so it never collides."""
return Path(slots[0].cache_dir) / f"{uid}.claim"
def read_claim(path):
try:
return json.loads(Path(path).read_text())
except (FileNotFoundError, ValueError, OSError):
return None
def try_claim(path, tag=""):
"""take <uid>.claim with O_EXCL. -> (True, None) when we hold it; (False, owner) when a LIVE other pid holds it. A claim whose pid is dead (or unreadable) is
removed and re-taken once; losing that second race -> (False, owner). Any other OSError is logged by the caller and treated as ours (claims are advisory)."""
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
payload = json.dumps({"pid": os.getpid(), "utc": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "tag": str(tag or "")})
for attempt in range(2):
try:
fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o644)
except FileExistsError:
owner = read_claim(path)
if owner is not None and int(owner.get("pid", -1)) != os.getpid() and pid_alive(owner.get("pid", -1)):
return False, owner
if attempt == 1:
return False, owner
again = read_claim(path) # stale (pid dead / unreadable): take over, unless someone replaced it meanwhile
if again is not None and owner is not None and again.get("pid") != owner.get("pid"):
return False, again
with contextlib.suppress(FileNotFoundError):
os.unlink(path)
continue
with os.fdopen(fd, "w") as f:
f.write(payload)
return True, None
return False, read_claim(path)
def release_claim(path):
"""remove our claim (only when the file still carries our pid)."""
path = Path(path)
owner = read_claim(path)
if owner is not None and int(owner.get("pid", -1)) != os.getpid():
return False
with contextlib.suppress(FileNotFoundError):
os.unlink(path)
return True
def _npz_meta(path):
try:
with np.load(path, allow_pickle=False) as z:
return json.loads(str(z["meta"])) if "meta" in z.files else {}
except Exception:
return {}
def fresh_part_elsewhere(slots, uid, tag, minutes, now=None):
"""-> info dict when some <uid>.part.npz of the set (frame or window cache) was modified within `minutes` and was NOT written under our tag (meta.writer_tag missing =
a writer that predates the claim files, or another tag): that route is in progress in another process. None otherwise (or when minutes <= 0)."""
if not minutes or minutes <= 0:
return None
now = time.time() if now is None else now
for s in slots:
for p in (Path(s.cache_dir) / f"{uid}.part.npz",) + ((Path(s.win_dir) / f"{uid}.part.npz",) if s.is_window else ()):
try:
age_min = (now - p.stat().st_mtime) / 60.0
except FileNotFoundError:
continue
if age_min > minutes:
continue
wt = _npz_meta(p).get("writer_tag")
if wt is not None and str(wt) == str(tag or ""):
continue # our own earlier chunk
return {"path": str(p), "age_min": round(age_min, 1), "writer_tag": wt}
return None
# ----------------------------------------------------------------------------- the queue loop
def set_name_of(models):
for k, v in SETS.items():
if set(models) <= set(v):
return k
return "custom"
def run_queue(slots, rows, args, deadline, log):
t0 = time.time()
models = [s.name for s in slots]
set_name = args.tag or set_name_of(models)
tiers = {t: {"routes_total": 0, "frames_total": 0, "routes_done": 0, "frames_done": 0, "routes_skipped_existing": 0} for t in TIERS}
for r in rows:
tiers[r["tier"]]["routes_total"] += 1
tiers[r["tier"]]["frames_total"] += r["n_frames10"]
recent = [] # (frames newly processed, wall s) of the last routes for the rolling fps
frames_new_total, fails, budget = 0, [], False
skipped = [] # routes without a pose cache: not work, not a failure (every frame would be fail 1)
deferred = {} # uid -> info of routes held by another process (claim / fresh .part); re-polled after the queue
infos = []
max_load = float(getattr(args, "max_load1", MAX_LOAD1) or MAX_LOAD1)
fresh_min = float(getattr(args, "skip_fresh_part_min", 0) or 0)
stamp = time.strftime("%Y%m%dT%H%M%SZ", time.gmtime())
log_dir = FULL_DIR / "logs"
log_dir.mkdir(parents=True, exist_ok=True)
def progress(current=None, note=""):
rec = {"set": set_name, "models": models, "pid": os.getpid(), "chunk_started_utc": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(t0)), "wall_s": round(time.time() - t0, 1),
"routes_total": sum(v["routes_total"] for v in tiers.values()), "routes_done": sum(v["routes_done"] for v in tiers.values()),
"frames_total": sum(v["frames_total"] for v in tiers.values()), "frames_done": sum(v["frames_done"] for v in tiers.values()), "frames_new_this_chunk": frames_new_total,
"fps_rolling": None, "fps_overall_chunk": round(frames_new_total / max(time.time() - t0, 1e-9), 2), "current_route": current, "note": note,
"routes_deferred_elsewhere": len(deferred), "tiers": {}}
fr = sum(a for a, _ in recent[-20:])
wl = sum(b for _, b in recent[-20:])
fps = fr / wl if wl > 0 and fr > 0 else None
rec["fps_rolling"] = None if fps is None else round(fps, 2)
for t, v in tiers.items():
rem = v["frames_total"] - v["frames_done"]
v2 = dict(v, frames_remaining=rem, eta_h=(None if not fps else round(rem / fps / 3600.0, 2)))
rec["tiers"][t] = v2
rec["eta_h_all"] = None if not fps else round(sum(v["frames_total"] - v["frames_done"] for v in tiers.values()) / fps / 3600.0, 2)
update_progress(set_name, rec)
return rec
def one_route(r, n_i, n_rows):
"""claim -> process -> release one queue row; -> (code, status). Deferred routes (held elsewhere) return (None, status) and touch no counter."""
nonlocal frames_new_total
fresh = fresh_part_elsewhere(slots, r["uid"], set_name, fresh_min)
if fresh is not None:
log(f"[{r['tier']} {n_i + 1}/{n_rows}] {r['uid'][:60]} in_progress_elsewhere (.part {fresh['age_min']} min old, writer_tag {fresh['writer_tag']}) -> deferred")
deferred[r["uid"]] = {"uid": r["uid"], "tier": r["tier"], "status": "in_progress_elsewhere", **fresh}
return None, "in_progress_elsewhere"
cp = claim_path(slots, r["uid"])
try:
got, owner = try_claim(cp, set_name)
except OSError as e: # claims are advisory: an unwritable claim dir must not stop the extraction
log(f"claim {cp.name}: {repr(e)[:80]} -> proceeding without a claim")
got, owner, cp = True, None, None
if not got:
log(f"[{r['tier']} {n_i + 1}/{n_rows}] {r['uid'][:60]} claimed_by_other (pid {owner.get('pid') if owner else '?'}, tag {owner.get('tag') if owner else '?'}) -> deferred")
deferred[r["uid"]] = {"uid": r["uid"], "tier": r["tier"], "status": "claimed_by_other", "owner": owner}
return None, "claimed_by_other"
deferred.pop(r["uid"], None)
try:
code, info = process_route(slots, r["uid"], r["spans_arr"], r["tier"], args.workers, args.block, deadline, models, l2cs_shared=(args.l2cs_detector == "shared"),
force=args.force, limit_frames=args.limit_frames, checkpoint_frames=args.checkpoint_frames, log=log, tag=set_name)
finally:
if cp is not None:
release_claim(cp)
infos.append({k: v for k, v in info.items() if k != "models"} | {"models": {m: {kk: vv for kk, vv in d.items() if kk in ("status", "n_rows", "n_new_rows", "valid_rate", "windows", "windows_valid")} for m, d in info.get("models", {}).items()}})
st = info["status"]
tv = tiers[r["tier"]]
if code == EXIT_FAIL:
fails.append({"uid": r["uid"], "status": st, "error": info.get("error")})
elif code == EXIT_DONE:
tv["routes_done"] += 1
tv["frames_done"] += r["n_frames10"]
if st == "exists":
tv["routes_skipped_existing"] += 1
if st in ("done", "budget"):
n_new = int(info.get("n_frames_decoded", 0))
frames_new_total += n_new
recent.append((n_new, float(info.get("wall_s", 0.0))))
if code == EXIT_BUDGET: # credit the partial frames
tv["frames_done"] += n_new
mods = " ".join(f"{m}:{d.get('status')}/{d.get('valid_rate') if d.get('valid_rate') is None else round(d['valid_rate'], 3)}" for m, d in info.get("models", {}).items())
log(f"[{r['tier']} {n_i + 1}/{n_rows}] {r['uid'][:60]} {st} frames {info.get('n_frames_decoded', 0)}/{r['n_frames10']} wall {info.get('wall_s')}s fps {info.get('fps')} | {mods}")
progress(current=r["uid"])
return code, st
progress(note="chunk start")
for n_i, r in enumerate(rows):
if time.time() > deadline:
budget = True
break
if not wait_for_resources(deadline, log, max_load=max_load):
budget = True
break
if not r["pose_cache"]:
log(f"[{r['tier']}] {r['uid'][:60]}: no pose cache -> skipped (every frame would be fail 1)")
skipped.append({"uid": r["uid"], "tier": r["tier"], "status": "no_pose"})
continue
code, st = one_route(r, n_i, len(rows))
if code == EXIT_BUDGET:
budget = True
break
by_uid = {r["uid"]: r for r in rows}
while deferred and not budget and time.time() < deadline: # stragglers held by another process: re-poll until they exist / are released or the budget ends
log(f"{len(deferred)} route(s) held elsewhere -> re-poll in {DEFER_POLL_S:.0f} s: {', '.join(u[:40] for u in list(deferred)[:5])}")
progress(note=f"waiting for {len(deferred)} route(s) held by another process")
time.sleep(min(DEFER_POLL_S, max(1.0, deadline - time.time())))
if time.time() > deadline:
break
for u in list(deferred):
if time.time() > deadline or not wait_for_resources(deadline, log, max_load=max_load):
budget = True
break
code, st = one_route(by_uid[u], rows.index(by_uid[u]), len(rows))
if code == EXIT_BUDGET:
budget = True
break
remaining = sum(v["routes_total"] - v["routes_done"] for v in tiers.values()) - len(fails) - len(skipped)
code = EXIT_BUDGET if (budget or remaining > 0) else (EXIT_FAIL if fails else EXIT_DONE)
summ = {"set": set_name, "models": models, "exit_code": code, "budget_hit": budget, "routes_remaining": int(max(remaining, 0)), "n_failed": len(fails), "fails": fails[:50],
"n_skipped_no_pose": len(skipped), "skipped_no_pose": skipped[:50], "n_deferred_elsewhere": len(deferred), "deferred_elsewhere": list(deferred.values())[:50],
"frames_new_this_chunk": frames_new_total, "wall_s": round(time.time() - t0, 1), "tiers": tiers, "args": {k: v for k, v in vars(args).items()}, "routes": infos[-400:]}
(log_dir / f"chunk_{set_name}_{stamp}.json").write_text(json.dumps(summ, indent=1, default=str))
progress(note=("BUDGET_EXIT" if code == EXIT_BUDGET else ("ALL_DONE" if code == EXIT_DONE else "FAILURES")))
log(("BUDGET_EXIT " if code == EXIT_BUDGET else ("ALL_DONE " if code == EXIT_DONE else "FAILURES ")) + json.dumps({k: summ[k] for k in ("routes_remaining", "n_failed", "frames_new_this_chunk", "wall_s")}))
return code
# ----------------------------------------------------------------------------- Phase-1 equality check
def manifest_spans(uids):
import pandas as pd
M = pd.read_csv(MANIFEST)
return {u: cs.merge_spans(M.loc[M.uid == u, ["win_start", "win_end"]].to_numpy(np.float64)) for u in uids}, M
def compare_frame_caches(a: cs.RouteCache, b: cs.RouteCache):
"""a = new, b = Phase 1 -> dict(n_common, n_valid_both, max_abs_diff (f32 of the f16 values), n_rows_differ_any (> f16 ulp), valid_agree share, only_in_new / only_in_old)."""
ka, kb = a.frame_idx, b.frame_idx
common, ia, ib = np.intersect1d(ka, kb, return_indices=True)
va, vb = a.valid[ia], b.valid[ib]
both = va & vb
Fa, Fb = a.feat[ia].astype(np.float32), b.feat[ib].astype(np.float32)
d = np.abs(Fa[both] - Fb[both])
ulp = np.maximum(np.abs(Fb[both]), 1e-3) * 2.0 ** -10 # one f16 ulp of the stored value
out = {"n_common": int(len(common)), "n_valid_both": int(both.sum()), "valid_agree_share": float((va == vb).mean()) if len(common) else None,
"n_valid_only_new": int((va & ~vb).sum()), "n_valid_only_old": int((~va & vb).sum()), "n_only_in_new": int(len(ka) - len(common)), "n_only_in_old": int(len(kb) - len(common)),
"max_abs_diff": float(d.max()) if d.size else 0.0, "median_abs_diff": float(np.median(d)) if d.size else 0.0,
"rows_exact": int((d.max(1) == 0).sum()) if d.size else 0, "rows_within_1_f16_ulp": int((d <= ulp).all(1).sum()) if d.size else 0,
"max_abs_diff_per_channel": {c: float(d[:, j].max()) for j, c in enumerate(a.channels)} if d.size and a.C <= 40 else None}
if d.size and a.C > 40:
out["max_abs_diff_top5_channels"] = {a.channels[j]: float(d[:, j].max()) for j in np.argsort(-d.max(0))[:5]}
return out
def compare_window_caches(a: cs.WindowCache, b: cs.WindowCache):
ka, kb = np.round(a.win_t_end.astype(np.float64) * cs.HZ).astype(np.int64), np.round(b.win_t_end.astype(np.float64) * cs.HZ).astype(np.int64)
common, ia, ib = np.intersect1d(ka, kb, return_indices=True)
va, vb = a.win_valid[ia], b.win_valid[ib]
both = va & vb
Ea, Eb = a.emb[ia].astype(np.float32), b.emb[ib].astype(np.float32)
d = np.abs(Ea[both] - Eb[both])
ulp = np.maximum(np.abs(Eb[both]), 1e-3) * 2.0 ** -10
return {"n_common": int(len(common)), "n_valid_both": int(both.sum()), "n_valid_only_new": int((va & ~vb).sum()), "n_valid_only_old": int((~va & vb).sum()),
"max_abs_diff": float(d.max()) if d.size else 0.0, "median_abs_diff": float(np.median(d)) if d.size else 0.0, "rows_exact": int((d.max(1) == 0).sum()) if d.size else 0,
"rows_within_1_f16_ulp": int((d <= ulp).all(1).sum()) if d.size else 0, "emb_abs_p50": float(np.median(np.abs(Eb[both]))) if d.size else None}
def verify_phase1(models, uids, args, log=print):
out_root = FULL_DIR / "verify_phase1"
spans, M = manifest_spans(uids)
det = args.l2cs_detector or "own"
if det == "shared" and "l2cs_gaze" in models and "openface3" not in models:
models = ["openface3"] + list(models)
slots = [Slot(m, args.device, out_root, det).setup(log) for m in models]
deadline = time.time() + args.max_minutes * 60
rep = {"written_utc": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "models": list(models), "uids": list(uids), "out_root": str(out_root), "l2cs_detector": det, "routes": {}, "per_model": {}}
for u in uids:
code, info = process_route(slots, u, spans[u], "V", args.workers, args.block, deadline, models, l2cs_shared=(det == "shared"), force=True, log=log)
rep["routes"][u] = {k: v for k, v in info.items() if k in ("status", "n_frames_decoded", "wall_s", "fps", "decode_worker_fps")}
log(f"verify {u[:60]} {info['status']} frames {info.get('n_frames_decoded')} wall {info.get('wall_s')}s")
for s in slots:
per = {}
for u in uids:
p_new, p_old = s.cache_dir / f"{u}.npz", PHASE1 / s.name / "cache" / f"{u}.npz"
if not (p_new.exists() and p_old.exists()):
per[u] = {"error": f"missing {'new' if not p_new.exists() else 'phase1'} cache"}
continue
per[u] = {"frames": compare_frame_caches(cs.RouteCache.load(p_new), cs.RouteCache.load(p_old))}
if s.is_window:
pw_new, pw_old = s.win_dir / f"{u}.npz", PHASE1 / s.name / PHASE1_WINDOW_DIR[s.name] / f"{u}.npz"
if pw_new.exists() and pw_old.exists():
per[u]["windows"] = compare_window_caches(cs.WindowCache.load(pw_new), cs.WindowCache.load(pw_old))
fr = [v["frames"] for v in per.values() if "frames" in v]
wn = [v["windows"] for v in per.values() if "windows" in v]
rep["per_model"][s.name] = {"routes": per,
"frames_max_abs_diff": max([f["max_abs_diff"] for f in fr] or [None]), "frames_n_valid_both": sum(f["n_valid_both"] for f in fr), "frames_rows_exact": sum(f["rows_exact"] for f in fr),
"frames_rows_within_1_f16_ulp": sum(f["rows_within_1_f16_ulp"] for f in fr), "frames_valid_only_new": sum(f["n_valid_only_new"] for f in fr), "frames_valid_only_old": sum(f["n_valid_only_old"] for f in fr),
"windows_max_abs_diff": (max(w["max_abs_diff"] for w in wn) if wn else None), "windows_n_valid_both": (sum(w["n_valid_both"] for w in wn) if wn else None),
"windows_rows_exact": (sum(w["rows_exact"] for w in wn) if wn else None), "windows_rows_within_1_f16_ulp": (sum(w["rows_within_1_f16_ulp"] for w in wn) if wn else None),
"windows_valid_only_new": (sum(w["n_valid_only_new"] for w in wn) if wn else None), "windows_valid_only_old": (sum(w["n_valid_only_old"] for w in wn) if wn else None)}
out_root.mkdir(parents=True, exist_ok=True)
tag = args.tag or set_name_of(models)
(out_root / f"verify_phase1_{tag}.json").write_text(json.dumps(rep, indent=1, default=str))
lines = [f"l2cs detector: {det}", "", "| model | rows valid in both | rows exact | rows within 1 f16 ulp | max abs diff | valid only new / only phase1 | windows valid both | windows exact / within ulp | windows max abs diff |", "|---|---|---|---|---|---|---|---|---|"]
for m, v in rep["per_model"].items():
lines.append(f"| {m} | {v['frames_n_valid_both']} | {v['frames_rows_exact']} | {v['frames_rows_within_1_f16_ulp']} | {v['frames_max_abs_diff']} | {v['frames_valid_only_new']} / {v['frames_valid_only_old']} | "
f"{v['windows_n_valid_both']} | {v['windows_rows_exact']} / {v['windows_rows_within_1_f16_ulp']} | {v['windows_max_abs_diff']} |")
(out_root / f"verify_phase1_{tag}.md").write_text("\n".join(lines) + "\n")
print("\n".join(lines))
for s in slots:
s.ex.teardown()
return 0
# ----------------------------------------------------------------------------- l2cs shared-detector check
def l2cs_detector_check(args, log=print):
"""the 45 Phase-1 routes: openface3.detect_faces box -> l2cs infer_with_boxes vs the Phase-1 l2cs caches (own detector): Spearman rho, median |d|, box IoU."""
from scipy.stats import spearmanr
import pandas as pd
M = pd.read_csv(MANIFEST)
uids = list(dict.fromkeys(M.uid))
spans, _ = manifest_spans(uids)
of3 = Slot("openface3", args.device).setup(log)
l2 = Slot("l2cs_gaze", args.device, l2cs_detector="shared").setup(log)
rows = [] # (uid, k, yaw_sh, pitch_sh, conf_sh, bw_sh, iou, own_found, yaw_own, pitch_own, conf_own)
t_all = time.time()
det_ms, own_ms = [], []
for n_u, u in enumerate(uids):
fs = vio.FrameStream(u, spans[u], hz=cs.HZ, workers=args.workers, decode_wh=None, block=args.block, box_coords="native")
pend = []
def flush():
if not pend:
return
crops = [c for _, c in pend]
t0 = time.time()
dets = of3.ex.detect_faces(crops)
t1 = time.time()
sh = l2.ex.infer_with_boxes(crops, dets)
own = l2.ex.detect_largest(crops)
t2 = time.time()
det_ms.append(1000.0 * (t1 - t0) / len(crops))
own_ms.append(1000.0 * (t2 - t1) / len(crops))
for (k, _), d, r, o in zip(pend, dets, sh, own):
iou = np.nan
if o is not None and np.isfinite(d).all():
a, b = d[:4], o[0]
ix = max(0.0, min(a[2], b[2]) - max(a[0], b[0]))
iy = max(0.0, min(a[3], b[3]) - max(a[1], b[1]))
inter = ix * iy
ua = (a[2] - a[0]) * (a[3] - a[1]) + (b[2] - b[0]) * (b[3] - b[1]) - inter
iou = inter / ua if ua > 0 else np.nan
rows.append((u, k, float(r[1]), float(r[2]), float(r[0]), float(r[3]), float(iou), o is not None, float(d[4]) if np.isfinite(d[4]) else np.nan))
pend.clear()
for t_, fi_, fr_, bx_ in fs:
k = int(round(float(t_) * cs.HZ))
crop = vio.driver_crop(fr_, bx_) if fr_ is not None else None
if crop is not None:
pend.append((k, np.ascontiguousarray(crop)))
if len(pend) >= 64:
flush()
flush()
log(f"[{n_u + 1}/{len(uids)}] {u[:60]} frames {len(fs.frame_idx)} wall {fs.stats['wall_s']:.1f}s")
# compare with the Phase-1 caches
R = pd.DataFrame(rows, columns=["uid", "k", "yaw_sh", "pitch_sh", "conf_sh", "bw_sh", "iou", "own_found", "score_of3"])
old = []
for u in uids:
rc = cs.RouteCache.load(PHASE1 / "l2cs_gaze" / "cache" / f"{u}.npz")
kk = np.round(rc.t.astype(np.float64) * cs.HZ).astype(np.int64)
F = rc.feat.astype(np.float32)
old.append(pd.DataFrame({"uid": u, "k": kk, "valid_old": rc.valid, "yaw_old": F[:, 1], "pitch_old": F[:, 2], "conf_old": F[:, 0], "bw_old": F[:, 3], "had_box": np.isfinite(rc.box).all(1)}))
O = pd.concat(old, ignore_index=True)
J = O.merge(R, on=["uid", "k"], how="left")
valid_sh = np.isfinite(J.yaw_sh.to_numpy()) & np.isfinite(J.pitch_sh.to_numpy())
valid_old = J.valid_old.to_numpy().astype(bool)
both = valid_sh & valid_old
def circ(a, b):
return ((a - b + 180.0) % 360.0) - 180.0
y_sh, y_old, p_sh, p_old = J.yaw_sh.to_numpy()[both], J.yaw_old.to_numpy()[both], J.pitch_sh.to_numpy()[both], J.pitch_old.to_numpy()[both]
dy, dp = circ(y_sh, y_old), circ(p_sh, p_old)
y_sh_unwrapped = y_old + dy # the shared value expressed next to the Phase-1 value (undoes the +-180 wrap)
rep = {"written_utc": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "n_routes": len(uids), "n_frames_phase1": int(len(J)), "n_frames_with_box": int(J.had_box.sum()),
"n_valid_phase1_own_detector": int(valid_old.sum()), "n_valid_shared_detector": int(valid_sh.sum()), "n_valid_both": int(both.sum()),
"n_valid_only_own": int((valid_old & ~valid_sh).sum()), "n_valid_only_shared": int((valid_sh & ~valid_old).sum()),
"spearman_rho_yaw_raw": float(spearmanr(y_sh, y_old).statistic), "spearman_rho_yaw_unwrapped": float(spearmanr(y_sh_unwrapped, y_old).statistic),
"spearman_rho_pitch": float(spearmanr(p_sh, p_old).statistic),
"median_abs_d_yaw_deg_circular": float(np.median(np.abs(dy))), "p90_abs_d_yaw_deg": float(np.percentile(np.abs(dy), 90)), "p99_abs_d_yaw_deg": float(np.percentile(np.abs(dy), 99)),
"median_abs_d_pitch_deg": float(np.median(np.abs(dp))), "p90_abs_d_pitch_deg": float(np.percentile(np.abs(dp), 90)), "p99_abs_d_pitch_deg": float(np.percentile(np.abs(dp), 99)),
"share_abs_d_yaw_le_1deg": float(np.mean(np.abs(dy) <= 1.0)), "share_abs_d_yaw_le_5deg": float(np.mean(np.abs(dy) <= 5.0)),
"box_iou_median_both_found": float(np.nanmedian(J.iou.to_numpy()[both])), "box_iou_p10_both_found": float(np.nanpercentile(J.iou.to_numpy()[both], 10)),
"box_w_median_abs_d_px": float(np.median(np.abs(J.bw_sh.to_numpy()[both] - J.bw_old.to_numpy()[both]))),
"conf_median_abs_d": float(np.median(np.abs(J.conf_sh.to_numpy()[both] - J.conf_old.to_numpy()[both]))),
"ms_per_crop_openface3_detector_batched_64": float(np.median(det_ms)) if det_ms else None, "ms_per_crop_l2cs_gaze_plus_own_detector": float(np.median(own_ms)) if own_ms else None,
"wall_s": round(time.time() - t_all, 1), "criterion": "adopt the shared box iff Spearman rho >= 0.95 for yaw (raw) and pitch on frames valid under both detectors"}
rep["decision"] = "shared" if (rep["spearman_rho_yaw_raw"] >= 0.95 and rep["spearman_rho_pitch"] >= 0.95) else "own"
FULL_DIR.mkdir(parents=True, exist_ok=True)
(FULL_DIR / "l2cs_shared_detector_check.json").write_text(json.dumps(rep, indent=1, default=str))
(FULL_DIR / "l2cs_detector_decision.json").write_text(json.dumps({"l2cs_detector": rep["decision"], "rho_yaw_raw": rep["spearman_rho_yaw_raw"], "rho_yaw_unwrapped": rep["spearman_rho_yaw_unwrapped"],
"rho_pitch": rep["spearman_rho_pitch"], "median_abs_d_yaw": rep["median_abs_d_yaw_deg_circular"], "median_abs_d_pitch": rep["median_abs_d_pitch_deg"],
"n_valid_both": rep["n_valid_both"], "written_utc": rep["written_utc"]}, indent=1))
print(json.dumps({k: v for k, v in rep.items() if not isinstance(v, (list, dict))}, indent=1))
of3.ex.teardown()
l2.ex.teardown()
return 0
# ----------------------------------------------------------------------------- CLI
def parse_models(s):
if s in SETS:
return list(SETS[s])
ms = [m.strip() for m in s.split(",") if m.strip()]
bad = [m for m in ms if m not in ALL_MODELS]
assert not bad, f"unknown models {bad}; known {ALL_MODELS}"
return ms
def select_rows(rows, tiers="A,B,C,D", uids=None, reverse=False, limit_routes=0):
"""the (tier, route) rows this process walks, in order: tier filter + local video -> optional --uids filter (queue order kept) -> optional --reverse -> optional
--limit-routes. Pure; the default arguments reproduce the pre-2026-09-15 selection exactly."""
tiers = [t.strip() for t in str(tiers).split(",") if t.strip()]
rows = [r for r in rows if r["tier"] in tiers and r["video_local"]]
if uids:
keep = set(uids)
rows = [r for r in rows if r["uid"] in keep]
if reverse:
rows = rows[::-1]
if limit_routes:
rows = rows[:limit_routes]
return rows
def build_parser():
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
ap.add_argument("--models", default="cpu", help="cpu | gpu | comma list of " + ",".join(ALL_MODELS))
ap.add_argument("--workers", type=int, default=4, help="decode worker processes (2 ffmpeg threads each)")
ap.add_argument("--block", type=int, default=32, help="native frames per decode block (2 x workers blocks in flight; 32 x 8 x 7 MB ~ 1.8 GB)")
ap.add_argument("--max-minutes", type=float, default=600.0)
ap.add_argument("--tiers", default="A,B,C,D")
ap.add_argument("--uids", default="", help="comma list or file: restrict to these routes (queue order kept)")
ap.add_argument("--out-root", default="", help="cache root (default results/baselines_dms -> cache/<b>/); smoke runs use another root")
ap.add_argument("--device", default="cuda:0")
ap.add_argument("--l2cs-detector", default="", choices=["", "own", "shared"], help="default: full/l2cs_detector_decision.json if present, else own")
ap.add_argument("--build-queue", action="store_true", help="(re)write results/baselines_dms/full/route_queue.csv and exit")
ap.add_argument("--verify-phase1", action="store_true", help="manifest windows of --uids -> full/verify_phase1/<b>/, compared with the Phase-1 caches")
ap.add_argument("--l2cs-detector-check", action="store_true")
ap.add_argument("--limit-routes", type=int, default=0)
ap.add_argument("--limit-frames", type=int, default=0, help="stop a route after this many decoded frames (smoke: writes .part caches)")
ap.add_argument("--checkpoint-frames", type=int, default=6000, help="write .part caches every N decoded frames inside a route (0 = only at the budget)")
ap.add_argument("--force", action="store_true")
ap.add_argument("--tag", default="", help="progress record name (default cpu / gpu / custom); also the claim / writer tag")
ap.add_argument("--no-gpu-gate", action="store_true")
ap.add_argument("--reverse", action="store_true", help="walk the filtered queue from the end (second shard of a set)")
ap.add_argument("--max-load1", type=float, default=MAX_LOAD1, help=f"per-route gate: wait while the 1-min load is >= this (default {MAX_LOAD1})")
ap.add_argument("--skip-fresh-part-min", type=float, default=0.0,
help="defer a route whose .part.npz was written by another tag within the last N minutes (in progress in a process that predates the claims); 0 = off")
return ap
def main():
a = build_parser().parse_args()
t_start = time.time()
def log(m):
print(f"{time.strftime('%H:%M:%S')} {m}", flush=True)
if a.build_queue:
build_queue(log=log)
return 0
models = parse_models(a.models)
if a.l2cs_detector_check:
return l2cs_detector_check(a, log)
import cv2
cv2.setNumThreads(4)
if any(m in SETS["gpu"] for m in models) and str(a.device).startswith("cuda"):
import torch
torch.set_num_threads(int(os.environ.get("OMP_NUM_THREADS", "4")))
need = sum(NEED_VRAM_GB[m] for m in models if m in NEED_VRAM_GB) + VRAM_HEADROOM_GB
free = gpu_free_gb()
if not a.no_gpu_gate and not (free >= need):
log(f"GPU gate: free VRAM {free:.1f} GB < need {need:.1f} GB -> exit {EXIT_RESOURCES}")
return EXIT_RESOURCES
if mem_available_gb() < NEED_RAM_GB:
log(f"RAM gate: MemAvailable {mem_available_gb():.1f} GB < {NEED_RAM_GB} -> exit {EXIT_RESOURCES}")
return EXIT_RESOURCES
uids = None
if a.uids:
uids = [l.strip() for l in open(a.uids)] if Path(a.uids).exists() else [u.strip() for u in a.uids.split(",")]
uids = [u for u in uids if u]
if not a.l2cs_detector:
dec = FULL_DIR / "l2cs_detector_decision.json"
a.l2cs_detector = json.loads(dec.read_text())["l2cs_detector"] if dec.exists() else "own"
if a.verify_phase1:
assert uids, "--verify-phase1 needs --uids"
a.max_minutes = max(a.max_minutes, 240.0)
return verify_phase1(models, uids, a, log)
out_root = Path(a.out_root) if a.out_root else cs.RESULTS_ROOT
if not QUEUE_CSV.exists():
build_queue(log=log)
rows = select_rows(load_queue(), a.tiers, uids, a.reverse, a.limit_routes)
log(f"queue: {len(rows)} (tier, route) entries, {sum(r['n_frames10'] for r in rows)} frames @ 10 Hz{' (REVERSED)' if a.reverse else ''}; models {models}; "
f"l2cs detector {a.l2cs_detector}; out_root {out_root}; max load1 {a.max_load1}; skip fresh .part {a.skip_fresh_part_min} min")
if a.l2cs_detector == "shared" and "l2cs_gaze" in models and "openface3" not in models:
models = ["openface3"] + models # the shared box needs the openface3 detector in the process
log("shared l2cs detector: openface3 added to the set")
slots = [Slot(m, a.device, out_root, a.l2cs_detector).setup(log) for m in models]
deadline = t_start + a.max_minutes * 60.0
code = run_queue(slots, rows, a, deadline, log)
for s in slots:
try:
s.ex.teardown()
except Exception:
pass
return code
if __name__ == "__main__":
sys.exit(main())

Xet Storage Details

Size:
71.9 kB
·
Xet hash:
38b5c7850db27afab861849c278572105e98a1507589471cbe1e4c6a2120cd89

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.