Download code/offload/dspark/spark/remote_dspark/config.py from ProprietaryLegal/dsv41-sampled-drafting: direct link, hf CLI and curl.
- Browser
- Download file 20.4 kB
-
https://huggingface.co/ProprietaryLegal/dsv41-sampled-drafting/resolve/main/code/offload/dspark/spark/remote_dspark/config.py
- Command line
-
hf download hf://ProprietaryLegal/dsv41-sampled-drafting/code/offload/dspark/spark/remote_dspark/config.py
-
curl -L -o config.py https://huggingface.co/ProprietaryLegal/dsv41-sampled-drafting/resolve/main/code/offload/dspark/spark/remote_dspark/config.py
20.4 kB
| # SPDX-License-Identifier: Apache-2.0 | |
| """Environment configuration of the remote DSpark proxy (Spark side). | |
| The overlay is inactive unless VLLM_DSPARK_REMOTE is set (then the image's own code | |
| path runs byte-identically). Every value is validated at startup; a bad value raises. | |
| VLLM_DSPARK_REMOTE endpoint for rank 0: o1rdma://10.202.28.1:18620 (lane O1's ofl, RDMA), | |
| o1tcp://... (ofl's TCP backend) or tcp://... (the contract's TCP stub) | |
| VLLM_DSPARK_REMOTE_BIND this side's direct-link IPv4 (10.202.28.2); same as ?bind= in the | |
| endpoint, without a '?' that a launcher shell could glob | |
| VLLM_DSPARK_REMOTE_OFL_DIR directory holding libofl.so + ofl.py (o1tcp/o1rdma endpoints) | |
| VLLM_DSPARK_REMOTE_POLICY shadow (default) | resilience | capacity | |
| VLLM_DSPARK_REMOTE_IDENTITY 64-hex drafter identity (CONTRACT 6.7); required | |
| VLLM_DSPARK_REMOTE_MARKOV_IDENTITY 64-hex; default: sha256 of the VLLM_DSPARK_MARKOV_CACHE | |
| file, zeros if that variable is unset | |
| VLLM_DSPARK_REMOTE_TIMEOUT_MS per-round deadline (default 50) | |
| VLLM_DSPARK_REMOTE_CONNECT_TIMEOUT_MS connect + HELLO deadline (default 1000) | |
| VLLM_DSPARK_REMOTE_BACKOFF_MS first reconnect delay after a failure (default 1000, | |
| doubles up to VLLM_DSPARK_REMOTE_BACKOFF_MAX_MS, default 30000) | |
| VLLM_DSPARK_REMOTE_ON_FAIL target_only (default) | raise (capacity policy) | |
| VLLM_DSPARK_REMOTE_TRIP circuit breaker (CONTRACT 10, breaker.py): consecutive failed attempts | |
| before the remote is skipped (default 3; 0 = off) | |
| VLLM_DSPARK_REMOTE_COOLDOWN rounds without network after a trip, then one probe (default 256) | |
| VLLM_DSPARK_REMOTE_STRICT_START 1: raise at startup if connect + HELLO fails (default 0) | |
| VLLM_DSPARK_REMOTE_SHADOW_USE local (default) | remote (shadow policy) | |
| VLLM_DSPARK_REMOTE_WANT_MARGIN 1: ask the worker for top1-top2 margins (default 1 in shadow) | |
| VLLM_DSPARK_REMOTE_DRAFT_MS remote draft round cost for the depth policy (ms, finite >= 0); | |
| replaces VLLM_DSPARK_DRAFT_MS in capacity/resilience | |
| VLLM_DSPARK_REMOTE_ROUND_MS verify-only forward table for remote mode: ms for depth 0..k | |
| (k + 1 finite values > 0, non-decreasing); replaces | |
| VLLM_DSPARK_ROUND_MS (whose live value includes the local | |
| drafter) in capacity/resilience. With VLLM_DSPARK_DEPTH_POLICY | |
| on, capacity/resilience need BOTH remote costs (no mixed cost | |
| model) and refuse "confr:<table>" (its own table includes the | |
| local drafter). Shadow keeps the local measurements. | |
| VLLM_DSPARK_REMOTE_ASYNC 1: capacity policy only - rank 0 does not block its CPU on the round; | |
| the engine stream and the round's proxy thread hand each round over | |
| through two words in registered host memory (streamsync.HostFlagSync); | |
| the proxy thread makes no CUDA call. Self-tested at startup; falls back | |
| to the synchronous round with a warning. Default 0. | |
| VLLM_DSPARK_REMOTE_ASYNC_PROXY async mode: where the round's proxy runs. thread (default): a Python thread of the | |
| engine process (needs the engine's GIL to publish). process: a torch-free child | |
| process with its own interpreter (proxy_proc.py); the gather staging, the descriptor | |
| ring and the hand-off words share one registered memfd region (shmregion.py), so the | |
| success path never waits for the engine's GIL; the switch interval is not changed | |
| VLLM_DSPARK_REMOTE_HOSTFLAG_LIB async mode: path of libdsv41_hostflag.so (built from | |
| remote_dspark/hostflag.c). Default: VLLM_DSPARK_REMOTE_OFL_DIR's copy, | |
| else hostflag.c compiled with cc at startup. | |
| VLLM_DSPARK_REMOTE_ASYNC_NAP_US async mode: the proxy thread spins on the gathered word; > 0 = sleep this | |
| many us between checks after VLLM_DSPARK_REMOTE_ASYNC_SPIN_US of | |
| spinning (default 0: spin; one rank-0 core while a round is pending) | |
| VLLM_DSPARK_REMOTE_ASYNC_SPIN_US see ASYNC_NAP_US (default 1000) | |
| VLLM_DSPARK_REMOTE_ASYNC_WATCHDOG_MS async mode: a native watchdog fails and releases a round the engine stream | |
| gathered but nobody released within this many ms (zero drafts for that round), so a | |
| proxy thread that cannot run never parks the GPU for good. Default 0 = auto: | |
| max(4 x VLLM_DSPARK_REMOTE_TIMEOUT_MS, 200) | |
| VLLM_DSPARK_REMOTE_ASYNC_RESPAWNS async process mode: new proxy processes the engine may start after its proxy died | |
| or stalled (default 3; 0 = none: target-only rounds for the rest of the run). Between | |
| the loss and the new proxy's start every round is target-only (zero drafts); the new | |
| proxy starts with a new session, so the worker drops its windows and every slot is | |
| re-announced (NEW_GEN). Spent: target-only rounds, one error log line | |
| VLLM_DSPARK_REMOTE_ASYNC_RESPAWN_RESET_S a proxy process that served this long restores the full respawn budget | |
| (default 3600; 0 = never) | |
| VLLM_DSPARK_REMOTE_SWITCH_INTERVAL_US async thread mode: Python GIL switch interval while the proxy thread | |
| runs (default 500; the interpreter default is 5000; 0 = unchanged); ignored with | |
| ASYNC_PROXY=process | |
| VLLM_DSPARK_REMOTE_FUSED_GATHER auto (default: on CUDA, after a startup self-check against the torch | |
| path) | 0 | 1: the one-launch Triton row gather (fused_gather.py) | |
| VLLM_DSPARK_REMOTE_N_OUT auto (default) | 0: ReqEntry.n_out (CONTRACT 6.3). auto = cap[n] of the dynamic | |
| speculation schedule when the depth policy masks positions >= cap | |
| (conf/confb/confr, no VLLM_DSPARK_DEPTH_FILE) in capacity/resilience; | |
| otherwise, and in shadow, always all N positions | |
| VLLM_DSPARK_REMOTE_LOG_EVERY rounds between stats log lines (default 1024, 0 = off) | |
| VLLM_DSPARK_REMOTE_STATS_FILE JSON stats written by rank 0 (default | |
| /tmp/dsv41-remote-dspark.json, inside the container) | |
| """ | |
| from __future__ import annotations | |
| import hashlib | |
| import math | |
| import os | |
| from dataclasses import dataclass | |
| from . import wire | |
| from .transport import Endpoint, parse_endpoint | |
| POLICIES = ("shadow", "resilience", "capacity") | |
| ENV_ENDPOINT = "VLLM_DSPARK_REMOTE" | |
| def remote_requested(environ=None) -> bool: | |
| env = os.environ if environ is None else environ | |
| return bool((env.get(ENV_ENDPOINT) or "").strip()) | |
| def _int(env, key: str, default: int, lo: int = 0) -> int: | |
| raw = env.get(key) | |
| if raw is None or raw.strip() == "": | |
| return default | |
| try: | |
| v = int(raw) | |
| except ValueError as e: | |
| raise ValueError(f"{key}={raw!r}: not an integer") from e | |
| if v < lo: | |
| raise ValueError(f"{key}={v}: must be >= {lo}") | |
| return v | |
| def _choice(env, key: str, default: str, choices: tuple[str, ...]) -> str: | |
| v = (env.get(key) or default).strip().lower() | |
| if v not in choices: | |
| raise ValueError(f"{key}={v!r}: expected one of {choices}") | |
| return v | |
| def _bool(env, key: str, default: bool) -> bool: | |
| raw = env.get(key) | |
| if raw is None or raw.strip() == "": | |
| return default | |
| v = raw.strip().lower() | |
| if v in ("1", "true", "on", "yes"): | |
| return True | |
| if v in ("0", "false", "off", "no"): | |
| return False | |
| raise ValueError(f"{key}={raw!r}: expected 0 or 1") | |
| def _float_list(env, key: str) -> list[float] | None: | |
| raw = env.get(key) | |
| if raw is None or raw.strip() == "": | |
| return None | |
| try: | |
| vals = [float(x) for x in raw.split(",") if x.strip()] | |
| except ValueError as e: | |
| raise ValueError(f"{key}={raw!r}: expected comma-separated numbers") from e | |
| if not vals or not all(math.isfinite(v) for v in vals): | |
| raise ValueError(f"{key}={raw!r}: expected finite numbers") | |
| if any(v < 0 for v in vals): | |
| raise ValueError(f"{key}={raw!r}: expected non-negative numbers") | |
| return vals | |
| class RemoteConfig: | |
| endpoint: Endpoint | |
| policy: str | |
| drafter_identity: bytes | |
| markov_identity: bytes | |
| timeout_ms: int | |
| connect_timeout_ms: int | |
| backoff_ms: int | |
| backoff_max_ms: int | |
| on_fail: str | |
| strict_start: bool | |
| shadow_use: str | |
| want_margin: bool | |
| remote_draft_ms: float | None | |
| remote_round_ms: list[float] | None | |
| log_every: int | |
| stats_file: str | |
| async_mode: bool = False | |
| switch_interval_us: int = 500 | |
| hostflag_lib: str = "" | |
| async_nap_us: int = 0 | |
| async_spin_us: int = 1000 | |
| async_watchdog_ms: int = 0 | |
| async_proxy: str = "thread" | |
| async_respawns: int = 3 | |
| async_respawn_reset_s: int = 3600 | |
| fused_gather: bool | None = None | |
| n_out: str = "auto" | |
| trip: int = 3 | |
| cooldown: int = 256 | |
| sampled_top32: bool = False | |
| def watchdog_ms(self) -> int: | |
| """The async watchdog deadline actually used.""" | |
| return self.async_watchdog_ms or max(4 * self.timeout_ms, 200) | |
| def keeps_local_drafter(self) -> bool: | |
| return self.policy in ("shadow", "resilience") | |
| def from_env(cls, environ=None) -> "RemoteConfig": | |
| env = os.environ if environ is None else environ | |
| if not remote_requested(env): | |
| raise ValueError(f"{ENV_ENDPOINT} is not set") | |
| endpoint = parse_endpoint(env[ENV_ENDPOINT]) | |
| bind = (env.get("VLLM_DSPARK_REMOTE_BIND") or "").strip() | |
| if bind: | |
| if endpoint.options.get("bind", bind) != bind: | |
| raise ValueError(f"VLLM_DSPARK_REMOTE_BIND={bind} conflicts with the endpoint's " | |
| f"?bind={endpoint.options['bind']}") | |
| endpoint.options["bind"] = bind | |
| policy = _choice(env, "VLLM_DSPARK_REMOTE_POLICY", "shadow", POLICIES) | |
| ident_raw = env.get("VLLM_DSPARK_REMOTE_IDENTITY", "") | |
| if not ident_raw.strip(): | |
| raise ValueError( | |
| "VLLM_DSPARK_REMOTE_IDENTITY is required: the 64-hex drafter identity " | |
| "(offload/dspark/spark/tools/identity.py over lane S2's DSPARK_COPY_DONE.json)") | |
| drafter_identity = wire.parse_hex32(ident_raw, "VLLM_DSPARK_REMOTE_IDENTITY") | |
| markov_raw = env.get("VLLM_DSPARK_REMOTE_MARKOV_IDENTITY", "") | |
| if markov_raw.strip(): | |
| markov_identity = wire.parse_hex32(markov_raw, "VLLM_DSPARK_REMOTE_MARKOV_IDENTITY") | |
| else: | |
| markov_identity = markov_identity_from_env(env) | |
| draft_ms_list = _float_list(env, "VLLM_DSPARK_REMOTE_DRAFT_MS") | |
| if draft_ms_list is not None and len(draft_ms_list) != 1: | |
| raise ValueError("VLLM_DSPARK_REMOTE_DRAFT_MS: one number (ms)") | |
| cfg = cls( | |
| endpoint=endpoint, | |
| policy=policy, | |
| drafter_identity=drafter_identity, | |
| markov_identity=markov_identity, | |
| timeout_ms=_int(env, "VLLM_DSPARK_REMOTE_TIMEOUT_MS", 50, lo=1), | |
| connect_timeout_ms=_int(env, "VLLM_DSPARK_REMOTE_CONNECT_TIMEOUT_MS", 1000, lo=1), | |
| backoff_ms=_int(env, "VLLM_DSPARK_REMOTE_BACKOFF_MS", 1000, lo=1), | |
| backoff_max_ms=_int(env, "VLLM_DSPARK_REMOTE_BACKOFF_MAX_MS", 30000, lo=1), | |
| on_fail=_choice(env, "VLLM_DSPARK_REMOTE_ON_FAIL", "target_only", | |
| ("target_only", "raise")), | |
| strict_start=_bool(env, "VLLM_DSPARK_REMOTE_STRICT_START", False), | |
| shadow_use=_choice(env, "VLLM_DSPARK_REMOTE_SHADOW_USE", "local", | |
| ("local", "remote")), | |
| want_margin=_bool(env, "VLLM_DSPARK_REMOTE_WANT_MARGIN", policy == "shadow"), | |
| remote_draft_ms=None if draft_ms_list is None else draft_ms_list[0], | |
| remote_round_ms=_float_list(env, "VLLM_DSPARK_REMOTE_ROUND_MS"), | |
| log_every=_int(env, "VLLM_DSPARK_REMOTE_LOG_EVERY", 1024, lo=0), | |
| stats_file=(env.get("VLLM_DSPARK_REMOTE_STATS_FILE") | |
| or "/tmp/dsv41-remote-dspark.json"), | |
| async_mode=_bool(env, "VLLM_DSPARK_REMOTE_ASYNC", False), | |
| switch_interval_us=_int(env, "VLLM_DSPARK_REMOTE_SWITCH_INTERVAL_US", 500, lo=0), | |
| hostflag_lib=(env.get("VLLM_DSPARK_REMOTE_HOSTFLAG_LIB") or "").strip(), | |
| async_nap_us=_int(env, "VLLM_DSPARK_REMOTE_ASYNC_NAP_US", 0, lo=0), | |
| async_spin_us=_int(env, "VLLM_DSPARK_REMOTE_ASYNC_SPIN_US", 1000, lo=0), | |
| async_watchdog_ms=_int(env, "VLLM_DSPARK_REMOTE_ASYNC_WATCHDOG_MS", 0, lo=0), | |
| async_proxy=_choice(env, "VLLM_DSPARK_REMOTE_ASYNC_PROXY", "thread", ("thread", "process")), | |
| async_respawns=_int(env, "VLLM_DSPARK_REMOTE_ASYNC_RESPAWNS", 3, lo=0), | |
| async_respawn_reset_s=_int(env, "VLLM_DSPARK_REMOTE_ASYNC_RESPAWN_RESET_S", 3600, lo=0), | |
| fused_gather={"auto": None, "1": True, "0": False}[ | |
| _choice(env, "VLLM_DSPARK_REMOTE_FUSED_GATHER", "auto", ("auto", "0", "1"))], | |
| n_out=_choice(env, "VLLM_DSPARK_REMOTE_N_OUT", "auto", ("auto", "0")), | |
| sampled_top32=_bool(env, "VLLM_DSPARK_SAMPLED_TOP32", False), | |
| trip=_int(env, "VLLM_DSPARK_REMOTE_TRIP", 3, lo=0), | |
| cooldown=_int(env, "VLLM_DSPARK_REMOTE_COOLDOWN", 256, lo=1), | |
| ) | |
| if cfg.async_mode and cfg.policy != "capacity": | |
| raise ValueError("VLLM_DSPARK_REMOTE_ASYNC=1 needs VLLM_DSPARK_REMOTE_POLICY=capacity " | |
| "(resilience/shadow decide on the host every round)") | |
| if cfg.async_mode and cfg.on_fail == "raise": | |
| raise ValueError("VLLM_DSPARK_REMOTE_ASYNC=1 cannot raise on a failed round " | |
| "(the host never waits for it); use ON_FAIL=target_only") | |
| if cfg.backoff_max_ms < cfg.backoff_ms: | |
| raise ValueError("VLLM_DSPARK_REMOTE_BACKOFF_MAX_MS < VLLM_DSPARK_REMOTE_BACKOFF_MS") | |
| return cfg | |
| def markov_identity_from_env(env) -> bytes: | |
| path = (env.get("VLLM_DSPARK_MARKOV_CACHE") or "").strip() | |
| if not path: | |
| return bytes(32) | |
| try: | |
| with open(path, "rb") as f: | |
| return hashlib.sha256(f.read()).digest() | |
| except OSError as e: | |
| raise ValueError( | |
| f"VLLM_DSPARK_MARKOV_CACHE={path!r} unreadable ({e}); set " | |
| "VLLM_DSPARK_REMOTE_MARKOV_IDENTITY explicitly") from e | |
| def apply_cost_overrides(cfg: RemoteConfig, environ=None, depth_policy_on: bool = False, | |
| depth_mode: str | None = None, num_spec: int = 5, | |
| depth_file: str | None = None) -> dict[str, str]: | |
| """Make the remote round cost an explicit input of the depth policy (CONTRACT 10, | |
| brief "recalibration"). Writes VLLM_DSPARK_DRAFT_MS / VLLM_DSPARK_ROUND_MS in the | |
| process environment before the model runner builds DSparkDepthPolicy (it reads them | |
| in initialize_kv_cache, after the speculator exists; it is built only when | |
| VLLM_DSPARK_DEPTH_POLICY is on). Same env on both ranks, so the cost tables stay | |
| identical across TP ranks. Returns what was changed; raises before writing anything. | |
| The policy prices depth d as ROUND_MS[d] + DRAFT_MS (depth_policy.round_cost_ms). The | |
| live ROUND_MS includes the local drafter, so with the policy on, capacity/resilience | |
| need both remote inputs: a remote DRAFT_MS over the live table counts the drafter | |
| twice, a verify-only table under the live DRAFT_MS counts the wrong drafter. confr's | |
| table is part of the policy string and cannot take them at all. fixed:<d> never prices | |
| a depth, so it needs them only when a depth file can switch the mode at runtime.""" | |
| env = os.environ if environ is None else environ | |
| changed: dict[str, str] = {} | |
| if cfg.policy == "shadow": | |
| return changed # local drafter runs every round; timing is not representative | |
| if depth_policy_on and not (depth_mode == "fixed" and not depth_file): | |
| missing = [k for k, v in (("VLLM_DSPARK_REMOTE_DRAFT_MS", cfg.remote_draft_ms), | |
| ("VLLM_DSPARK_REMOTE_ROUND_MS", cfg.remote_round_ms)) | |
| if v is None] | |
| if missing: | |
| raise ValueError( | |
| f"remote DSpark ({cfg.policy}) with VLLM_DSPARK_DEPTH_POLICY needs both " | |
| "VLLM_DSPARK_REMOTE_DRAFT_MS (measured remote round, ms) and " | |
| "VLLM_DSPARK_REMOTE_ROUND_MS (verify-only table, ms by depth 0..k): missing " | |
| + " and ".join(missing) + ". The live VLLM_DSPARK_ROUND_MS includes the local " | |
| "drafter, so a partial override mixes two cost models") | |
| if depth_mode == "confr": | |
| raise ValueError( | |
| f"remote DSpark ({cfg.policy}): VLLM_DSPARK_DEPTH_POLICY=confr:<rows ms> carries " | |
| "its own step table (measured with the local drafter), which the remote cost " | |
| "inputs cannot replace; use conf or confb with VLLM_DSPARK_REMOTE_DRAFT_MS / " | |
| "VLLM_DSPARK_REMOTE_ROUND_MS") | |
| if cfg.remote_round_ms is not None: | |
| t = cfg.remote_round_ms | |
| if len(t) != num_spec + 1: | |
| raise ValueError(f"VLLM_DSPARK_REMOTE_ROUND_MS: {len(t)} values, expected " | |
| f"{num_spec + 1} (verify ms for depth 0..{num_spec})") | |
| if any(v <= 0 for v in t): | |
| raise ValueError("VLLM_DSPARK_REMOTE_ROUND_MS: verify times must be > 0 ms") | |
| if any(b < a for a, b in zip(t, t[1:])): | |
| raise ValueError("VLLM_DSPARK_REMOTE_ROUND_MS: must be non-decreasing with the " | |
| f"depth (more live rows never verify faster): {t}") | |
| changed["VLLM_DSPARK_ROUND_MS"] = ",".join(f"{v:g}" for v in t) | |
| if cfg.remote_draft_ms is not None: | |
| changed["VLLM_DSPARK_DRAFT_MS"] = f"{cfg.remote_draft_ms:g}" | |
| for k, v in changed.items(): | |
| env[k] = v | |
| return changed | |
| # depth-policy modes that zero the confidences at positions >= cap[num_reqs] before choosing | |
| # depths (DSparkDepthPolicy.record); "fixed" and "off" verify by the scheduler window only | |
| CAP_MASKING_DEPTH_MODES = ("conf", "confb", "confr") | |
| def n_out_table(cfg: RemoteConfig, num_spec: int, depth_mode: str, depth_file: str | None, | |
| dense_cap: list[int] | None) -> tuple[list[int] | None, str]: | |
| """ReqEntry.n_out by request count (CONTRACT 6.3), or None (always all N positions), | |
| with the reason. dense_cap is build_dynamic_sd_schedule_lookup's table (index = number | |
| of requests, index 0 unused), as the model runner passes it to DSparkDepthPolicy. | |
| Positions >= cap[n] are only safe to drop when nothing reads them: the depth policy | |
| must zero them (a cap-masking mode, fixed for the life of the serve, so no depth file | |
| that could switch it to "fixed"/"off"), and shadow compares every position.""" | |
| if cfg.policy == "shadow": | |
| return None, "shadow compares every position" | |
| if cfg.n_out == "0": | |
| return None, "VLLM_DSPARK_REMOTE_N_OUT=0" | |
| if depth_mode not in CAP_MASKING_DEPTH_MODES: | |
| return None, f"depth policy {depth_mode!r} does not mask positions >= cap" | |
| if depth_file: | |
| return None, "VLLM_DSPARK_DEPTH_FILE can switch the depth policy at runtime" | |
| if not dense_cap: | |
| return None, "no dynamic speculation schedule" | |
| table = [0 if i == 0 else min(num_spec, int(c)) for i, c in enumerate(dense_cap)] | |
| if all(c >= num_spec for c in table[1:]): | |
| return None, "schedule never caps below N" | |
| return table, "cap by request count" | |