ProprietaryLegal's picture
PLI Labs public snapshot 2026-10-28 (history squashed)
e1acc15
Raw History Blame Contribute Delete
24.3 kB
"""SP1-WINDOW cell driver: build public prompts once, then run one control or profiled cell per invocation.
Coordinator-only: offload/launch/windows/sp1_window.py calls it inside the HOLD through the owned tunnel 127.0.0.1:18001.
Without --execute it prints the cell plan and touches nothing. It records numbers and hashes only: no prompt or generated
text is written. Profiling uses vLLM's own /start_profile and /stop_profile (both TP ranks, collective RPC); a capture
starts only if the latest 1 s telemetry of both Sparks shows MemAvailable >= the capture floor, otherwise it is recorded
SKIPPED_MEMORY and the request still runs. See offload/gb10_budget/PROFILE-WINDOW-DESIGN.md.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import os
import threading
import time
import urllib.request
from collections.abc import Callable, Iterable, Iterator
from concurrent.futures import Future, ThreadPoolExecutor
from dataclasses import dataclass
from pathlib import Path
from typing import Protocol, cast
from offload.gb10_budget.capture import control, load_bench
from offload.prefill_maxlen.evidence import Json, number, record
from offload.prefill_trace.window_requests import HEADER, TEMPLATE, corpus, stream_summary
URL = 'http://127.0.0.1:18001'
CAP = 327680
TOLERANCE = .02 # built prompt: target*(1 - TOLERANCE) <= tokens <= target
MAX_COUNT_CALLS = 4 # /tokenize calls per prompt (PF1's bisection used 20-23; its dips reached 4.17 GiB)
FIRST_RATIO = 3.3 # characters per token, first guess (bench2 build_real)
SETTLE_S = 2.0 # decode capture starts this long after every stream emitted
DECODE_S = 3.0 # explicit stop after this; the profiler stops itself after 16 iterations first
PREFILL_S = 5.0 # 2-3 chunks of 4,092 tokens at ~1.85 s each
LATE_DELAY_S = 50.0 # 150K TTFT is 68.9-71.2 s (MEASURED PF1 W1/W3 off-327)
TTFT_TIMEOUT_S = 600.0
TELEMETRY_AGE_S = 3.0
@dataclass(frozen=True)
class Prompt:
key: str
target: int
offset: int # characters into the corpus body (after HEADER)
# Distinct, far-apart corpus offsets (11.8 M characters): no two cells send the same text.
PROMPTS = {p.key: p for p in (
Prompt('warm-32k', 32000, 9_000_000), Prompt('short', 1024, 0),
Prompt('32k-0', 32000, 1_000_000), Prompt('32k-1', 32000, 1_500_000), Prompt('32k-2', 32000, 2_000_000),
Prompt('32k-3', 32000, 2_500_000), Prompt('150k', 150000, 4_000_000))}
@dataclass(frozen=True)
class Cell:
name: str
prompts: tuple[str, ...]
captures: tuple[str, ...] = ()
max_tokens: int = 1500
warmup: bool = False
estimate_s: float = 60
late: int = 0 # WIN2: the last `late` prompts arrive only after every earlier stream is decoding
def __post_init__(self) -> None:
if not 0 <= self.late < len(self.prompts) or (self.late and (self.captures or self.warmup)):
raise ValueError(f'{self.name}: late arrivals need >= 1 early stream and no captures/warm-up')
@property
def batch(self) -> int:
return len(self.prompts)
B4 = ('32k-0', '32k-1', '32k-2', '32k-3')
CELLS = {c.name: c for c in (
Cell('warmup', ('warm-32k',), max_tokens=64, warmup=True, estimate_s=60),
Cell('ctl-short-b1', ('short',), estimate_s=60),
Cell('ctl-32k-b1', ('32k-0',), estimate_s=90),
Cell('ctl-32k-b4', B4, estimate_s=180),
Cell('ctl-150k-b1', ('150k',), estimate_s=180),
Cell('prof-short-b1', ('short',), ('decode',), estimate_s=120),
Cell('prof-32k-b1', ('32k-0',), ('prefill-early', 'decode'), estimate_s=150),
Cell('prof-32k-b4', B4, ('decode',), estimate_s=240),
Cell('prof-150k-b1', ('150k',), ('prefill-late', 'decode'), estimate_s=240),
# WIN2 (Fable review): multi-user and long-answer controls; not in ORDER, so existing windows are unchanged.
# mixed: three 32K decoders start (MEASURED 32K B1 TTFT ~14.5-15.4 s each; B3 contends), the 150K document arrives
# only after all three are decoding (MEASURED 150K TTFT 69 s alone, 117 s beside two decoders in PC1): ~300 s.
Cell('ctl-mixed150k-4user', ('32k-1', '32k-2', '32k-3', '150k'), late=1, estimate_s=300),
# long answer: 5,000 tokens at MEASURED 51-57 tok/s B1 decode ~ 90-100 s plus a short prefill: 180 s bound.
Cell('ctl-long-5k', ('short',), max_tokens=5000, estimate_s=180))}
WIN2_CELLS = ('ctl-mixed150k-4user', 'ctl-long-5k') # opt-in by name only
ORDER = tuple(n for n in CELLS if n not in WIN2_CELLS)
CAPTURE_KINDS = ('decode', 'prefill-early', 'prefill-late')
def body(materials: str) -> str:
if not materials.startswith(HEADER):
raise ValueError('corpus no longer starts with the benchmark header')
return materials[len(HEADER):]
def render(materials: str, offset: int, chars: int) -> str:
text = body(materials)
if offset < 0 or chars < 1 or offset + chars > len(text):
raise ValueError('prompt cut outside the public corpus; never repeat filler')
return HEADER + text[offset:offset + chars]
def cut(materials: str, prompt: Prompt, count: Callable[[str], int]) -> tuple[int, int]:
"""(characters, tokens) with target*(1-TOLERANCE) <= tokens <= target in at most MAX_COUNT_CALLS /tokenize calls."""
chars = int(prompt.target * FIRST_RATIO)
low = prompt.target * (1 - TOLERANCE)
for _ in range(MAX_COUNT_CALLS):
n = count(render(materials, prompt.offset, chars))
if n < 1:
raise ValueError('tokenizer returned no tokens')
if low <= n <= prompt.target:
return chars, n
chars = max(1, int(chars * prompt.target / n * (1 - TOLERANCE / 2))) # aim at the middle of the band
raise ValueError(f'{prompt.key}: no {prompt.target}-token cut within {MAX_COUNT_CALLS} /tokenize calls; window stops')
class Counters(Protocol):
"""bench2's /metrics parser and speculative-counter delta (reused, not copied)."""
def parse_metrics(self, text: str) -> dict[str, float]: ...
def spec_delta(self, before: dict[str, float], after: dict[str, float]) -> dict[str, Json]: ...
class Api(Protocol):
def tokens(self, text: str) -> int: ...
def metrics(self) -> str: ...
def model(self) -> dict[str, Json]: ...
def stream(self, body: dict[str, Json], first: threading.Event) -> dict[str, Json]: ...
def profile(self, verb: str) -> None: ...
def first_signal(lines: Iterable[bytes], first: threading.Event) -> Iterator[bytes]:
"""Pass SSE lines through unchanged; set `first` at the first reasoning/answer piece."""
for raw in lines:
if not first.is_set() and raw.startswith(b'data:') and raw[5:].strip() != b'[DONE]':
obj = record(cast(Json, json.loads(raw[5:].strip())))
choices = obj.get('choices') or []
for choice in choices if isinstance(choices, list) else []:
delta = record(record(choice).get('delta') or {})
if delta.get('reasoning_content') or delta.get('reasoning') or delta.get('content'):
first.set()
yield raw
class Http:
def __init__(self, url: str) -> None:
self.url = url
self.served: dict[str, Json] | None = None
def post(self, endpoint: str, body: dict[str, Json]) -> dict[str, Json]:
req = urllib.request.Request(self.url + endpoint, json.dumps(body).encode(), {'Content-Type': 'application/json'})
with urllib.request.urlopen(req, timeout=900) as response:
return record(cast(Json, json.load(response)))
def model(self) -> dict[str, Json]:
if self.served is None:
with urllib.request.urlopen(self.url + '/v1/models', timeout=10) as response:
models = record(cast(Json, json.load(response)))['data']
if not isinstance(models, list) or len(models) != 1:
raise ValueError('expected one served target')
self.served = record(models[0])
return self.served
def tokens(self, text: str) -> int:
result = self.post('/tokenize', {'model': self.model()['id'], 'messages': [{'role': 'user', 'content': text}],
'add_generation_prompt': True, 'chat_template_kwargs': TEMPLATE})
return int(number(result['count']))
def metrics(self) -> str:
with urllib.request.urlopen(self.url + '/metrics', timeout=10) as response:
return str(response.read().decode())
def stream(self, body: dict[str, Json], first: threading.Event) -> dict[str, Json]:
req = urllib.request.Request(self.url + '/v1/chat/completions', json.dumps(body).encode(),
{'Content-Type': 'application/json'})
started = time.monotonic()
with urllib.request.urlopen(req, timeout=900) as response:
return stream_summary(first_signal(response, first), started)
def profile(self, verb: str) -> None:
control(self.url, verb)
def busy(text: str) -> float:
total, seen = 0.0, set()
for line in text.splitlines():
for name in ('vllm:num_requests_running', 'vllm:num_requests_waiting'):
if line.startswith((name + '{', name + ' ')):
total += float(line.split()[-1])
seen.add(name)
if len(seen) != 2:
raise ValueError('metrics lack the request gauges')
return total
def running(text: str) -> float:
"""vllm:num_requests_running only (admitted requests), for late-arrival overlap proof."""
values = [float(line.split()[-1]) for line in text.splitlines()
if line.startswith(('vllm:num_requests_running{', 'vllm:num_requests_running '))]
if not values:
raise ValueError('metrics lack vllm:num_requests_running')
return sum(values)
def latest_memory(paths: list[Path], now: Callable[[], float] = time.time) -> dict[str, int]:
"""MemAvailable (kB) from the runner's 1 s telemetry files; refuses a stale or missing sample."""
found: dict[str, int] = {}
for path in paths:
if now() - path.stat().st_mtime > TELEMETRY_AGE_S:
raise RuntimeError(f'{path.name}: telemetry older than {TELEMETRY_AGE_S:g} s; capture floor cannot be checked')
rows = [record(cast(Json, json.loads(x))) for x in path.read_text().splitlines()[-8:] if x.startswith('{')]
memory = [r for r in rows if r.get('kind') == 'memory']
if not memory:
raise RuntimeError(f'{path.name}: no recent memory sample')
found[path.name] = int(number(record(memory[-1]['kb'])['MemAvailable']))
return found
@dataclass
class Plan:
deadline: float
floor_kb: int
telemetry: list[Path]
salt_prefix: str
ledger: Path | None = None
def salt(prefix: str, cell: str, stream: int) -> str:
if not prefix or not cell:
raise ValueError('invalid cache salt identity')
return f'{prefix}:{cell}:{stream}'
def run_cell(api: Api, cell: Cell, texts: dict[str, tuple[str, int]], plan: Plan, *,
sleep: Callable[[float], None] = time.sleep, clock: Callable[[], float] = time.monotonic,
wall: Callable[[], float] = time.time, cap: int = CAP, late_delay_s: float = LATE_DELAY_S) -> dict[str, Json]:
"""One cell. Captures always stop in `finally`; a stream failure propagates after the stop. `cap` and `late_delay_s`
are PF2-LOWKV's (524,288; mid-prompt at 35 s); SP1 uses the defaults."""
if wall() + cell.estimate_s > plan.deadline:
raise RuntimeError(f'window submission deadline reached: {cell.name} does not fit')
model = api.model()
if model.get('max_model_len') != cap:
raise ValueError('served cap differs from the profiled arm')
if busy(api.metrics()):
raise RuntimeError('serve not verified idle before the cell')
bench = cast(Counters, load_bench())
before = bench.parse_metrics(api.metrics())
origin = clock()
captures: list[dict[str, Json]] = []
firsts = [threading.Event() for _ in cell.prompts]
submitted: list[float] = [0.0] * cell.batch
early = cell.batch - cell.late
barrier = threading.Barrier(early)
late: dict[str, Json] = {}
def event(row: dict[str, Json]) -> None:
if plan.ledger is not None:
with plan.ledger.open('a') as handle:
handle.write(json.dumps({**row, 'cell': cell.name, 'time': wall()}) + '\n')
def request(i: int) -> dict[str, Json]:
key = cell.prompts[i]
text, tokens = texts[key]
cache = salt(plan.salt_prefix, cell.name, i)
body: dict[str, Json] = {'model': model['id'], 'messages': [{'role': 'user', 'content': text}],
'max_tokens': cell.max_tokens, 'temperature': 1.0, 'top_p': 1.0, 'seed': 42,
'priority': 10, 'cache_salt': cache, 'chat_template_kwargs': TEMPLATE,
'stream': True, 'stream_options': {'include_usage': True}}
if cell.warmup:
body['ignore_eos'] = True
if i < early:
barrier.wait(timeout=30)
submitted[i] = clock() - origin
event({'event': 'send', 'stream': i})
try:
summary = api.stream(body, firsts[i])
except BaseException as exc:
event({'event': 'failed', 'stream': i, 'error_class': type(exc).__name__})
raise
event({'event': 'completed', 'stream': i})
usage = record(summary['usage'])
cached = record(usage.get('prompt_tokens_details') or {}).get('cached_tokens')
if usage.get('prompt_tokens') != tokens or cached is None or number(cached) != 0:
raise ValueError('usage differs from the built prompt or a fresh salt hit the cache')
if cell.warmup and (usage.get('completion_tokens') != cell.max_tokens or summary.get('finish') != 'length'):
raise ValueError('warm-up did not generate its forced length')
response = summary.pop('response_id')
return {'stream': i, 'prompt': key, 'prompt_tokens': tokens, 'submitted_rel_s': submitted[i],
'prompt_sha256': hashlib.sha256(text.encode()).hexdigest(),
'cache_salt_sha256': hashlib.sha256(cache.encode()).hexdigest(),
'response_id_sha256': hashlib.sha256(str(response).encode()).hexdigest(),
'sampling': {'temperature': 1, 'top_p': 1, 'seed': 42, 'priority': 10, 'max_tokens': cell.max_tokens},
**summary}
futures: list[Future[dict[str, Json]]] = []
def submit() -> None:
futures.extend(pool.submit(request, i) for i in range(early))
if cell.late:
arrive_late()
def arrive_late() -> None:
"""Late streams start only after every early stream is decoding, and must be admitted beside them."""
end = clock() + TTFT_TIMEOUT_S
while not all(firsts[i].is_set() for i in range(early)):
check_failed()
if ended():
raise RuntimeError('an early stream ended before every early stream reached decode')
if clock() >= end:
raise TimeoutError('early streams did not all reach decode before the TTFT bound')
sleep(.02)
settle = clock() + SETTLE_S
while clock() < settle:
check_failed()
sleep(.05)
if ended():
raise RuntimeError('an early stream finished before the late arrival')
late['submitted_rel_s'] = clock() - origin
futures.extend(pool.submit(request, i) for i in range(early, cell.batch))
end = clock() + TTFT_TIMEOUT_S
while True:
check_failed()
if any(f.done() for f in futures[:early]):
raise RuntimeError('a decoder finished before the late arrival was admitted beside it')
if running(api.metrics()) >= cell.batch:
late['admitted_rel_s'] = clock() - origin
late['overlap'] = True
return
if clock() >= end:
raise TimeoutError('late arrival was never admitted beside the live decoders')
sleep(.05)
def ended() -> bool:
return any(f.done() for f in futures)
def check_failed() -> None:
for f in futures:
if f.done():
f.result() # propagate a stream failure instead of waiting for a bound
def capture(kind: str, then: Callable[[], None] | None = None) -> None:
"""Memory floor, start, optional action (submission), bounded wait, ALWAYS stop once started."""
row: dict[str, Json] = {'kind': kind}
captures.append(row)
memory = latest_memory(plan.telemetry)
row['mem_available_kb'] = cast(Json, memory)
if min(memory.values()) < plan.floor_kb:
row['status'] = 'SKIPPED_MEMORY'
if then is not None:
then()
return
row['start_call_rel_s'] = clock() - origin
api.profile('start_profile')
row['start_return_rel_s'] = clock() - origin
row['start_wall'] = wall()
try:
if then is not None:
then()
end = clock() + (DECODE_S if kind == 'decode' else PREFILL_S)
while clock() < end and not ended():
sleep(.05)
row['status'] = ('MIXED' if kind != 'decode' and any(f.is_set() for f in firsts) else # never "prefill"
'ENDED' if ended() else 'TAKEN')
finally:
row['stop_call_rel_s'] = clock() - origin
api.profile('stop_profile')
row['stop_return_rel_s'] = clock() - origin
row['stop_wall'] = wall()
with ThreadPoolExecutor(max_workers=cell.batch) as pool:
try:
if 'prefill-early' in cell.captures:
capture('prefill-early', submit) # the first chunks are the first iterations recorded
else:
submit()
if 'prefill-late' in cell.captures:
end = clock() + late_delay_s
while clock() < end:
check_failed()
if ended():
raise RuntimeError('stream ended before the late prefill capture')
sleep(.05)
if any(f.is_set() for f in firsts):
raise RuntimeError('decode already started; a late prefill capture would be mislabelled')
capture('prefill-late')
if 'decode' in cell.captures:
end = clock() + TTFT_TIMEOUT_S
while not all(f.is_set() for f in firsts):
check_failed()
if ended():
raise RuntimeError('a stream ended before every stream reached decode')
if clock() >= end:
raise TimeoutError('not every stream reached decode before the TTFT bound')
sleep(.02)
settle = clock() + SETTLE_S
while clock() < settle:
check_failed()
sleep(.05)
capture('decode')
finally:
while not all(f.done() for f in futures):
sleep(.05) # each stream keeps its own 900-second wall bound (stream_summary)
streams = [f.result() for f in futures]
after = bench.parse_metrics(api.metrics())
return {'type': 'cell', 'cell': cell.name, 'batch': cell.batch, 'profiled': bool(cell.captures),
'warmup': cell.warmup, 'origin_wall': wall() - (clock() - origin), 'late': cell.late,
'late_arrival': cast(Json, late or None),
'streams': cast(Json, streams), 'captures': cast(Json, captures),
'spec': cast(Json, bench.spec_delta(before, after)),
'status': 'MEASURED client observations; profiled cells are profile-affected, never promotion timings'}
def build(api: Api, materials: str, hashes: dict[str, Json]) -> dict[str, Json]:
if busy(api.metrics()):
raise RuntimeError('serve not verified idle before prompt construction')
prompts: dict[str, Json] = {}
for prompt in PROMPTS.values():
chars, tokens = cut(materials, prompt, api.tokens)
text = render(materials, prompt.offset, chars)
prompts[prompt.key] = {'target': prompt.target, 'offset': prompt.offset, 'chars': chars, 'tokens': tokens,
'sha256': hashlib.sha256(text.encode()).hexdigest()}
return {'type': 'cuts', 'corpus_sha256': hashes, 'header_sha256': hashlib.sha256(HEADER.encode()).hexdigest(),
'tolerance': TOLERANCE, 'prompts': prompts}
def texts_from(cuts: dict[str, Json], materials: str, hashes: dict[str, Json]) -> dict[str, tuple[str, int]]:
"""Re-render every prompt from its numeric cut; refuses any drift (no /tokenize call)."""
if cuts.get('corpus_sha256') != hashes:
raise ValueError('public corpus changed since the prompts were built')
out: dict[str, tuple[str, int]] = {}
for key, value in record(cuts['prompts']).items():
row = record(value)
prompt = PROMPTS[key]
if row.get('offset') != prompt.offset or row.get('target') != prompt.target:
raise ValueError('prompt plan changed since the prompts were built')
text = render(materials, prompt.offset, int(number(row['chars'])))
if hashlib.sha256(text.encode()).hexdigest() != row.get('sha256'):
raise ValueError(f'{key}: rebuilt prompt differs from its recorded hash')
out[key] = (text, int(number(row['tokens'])))
if set(out) != set(PROMPTS):
raise ValueError('incomplete prompt cuts')
return out
def main(argv: list[str] | None = None) -> int:
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument('--execute', action='store_true')
ap.add_argument('--url', default=URL)
ap.add_argument('--data-dir', type=Path, default=Path('/opt/dsv41/data/bench-data'))
sub = ap.add_subparsers(dest='command', required=True)
b = sub.add_parser('build', help='construct every prompt once; write numeric cuts and hashes only')
b.add_argument('--output', type=Path, required=True)
r = sub.add_parser('run', help='one cell')
r.add_argument('--cell', choices=ORDER, required=True)
r.add_argument('--cuts', type=Path, required=True)
r.add_argument('--output', type=Path, required=True)
r.add_argument('--deadline-utc', type=float, required=True)
r.add_argument('--telemetry', type=Path, nargs=2, required=True)
r.add_argument('--capture-floor-kb', type=int, required=True)
r.add_argument('--cache-salt-prefix', required=True)
r.add_argument('--ledger', type=Path)
args = ap.parse_args(argv)
if not args.execute:
print(json.dumps({'executed': False, 'cells': {n: {'prompts': list(c.prompts), 'captures': list(c.captures),
'max_tokens': c.max_tokens} for n, c in CELLS.items()},
'prompts': {k: {'target': p.target, 'offset': p.offset} for k, p in PROMPTS.items()}}))
return 0
if args.url != URL:
ap.error('coordinator must use the reserved experiment tunnel at 127.0.0.1:18001')
if args.output.exists():
ap.error('refusing an existing output; use a fresh window directory')
materials, hashes = corpus(args.data_dir)
api = Http(args.url)
if args.command == 'build':
result = build(api, materials, hashes)
else:
if args.deadline_utc <= time.time():
ap.error('--deadline-utc is in the past')
if not 4 * 1024**2 <= args.capture_floor_kb <= 8 * 1024**2:
ap.error('capture floor must lie in 4..8 GiB')
texts = texts_from(record(cast(Json, json.loads(args.cuts.read_text()))), materials, hashes)
plan = Plan(args.deadline_utc, args.capture_floor_kb, list(args.telemetry), args.cache_salt_prefix, args.ledger)
result = run_cell(api, CELLS[args.cell], texts, plan)
with args.output.open('x') as handle:
handle.write(json.dumps(result, allow_nan=False) + '\n')
print(f'{args.command}: wrote {args.output.name} (numbers and hashes only)')
return 0
if __name__ == '__main__':
raise SystemExit(main())