File size: 7,302 Bytes
919fd68 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | """Minimal public command line for prompting Nucleus Resynthesis Release 188."""
from __future__ import annotations
import argparse
import fcntl
import os
import subprocess
from collections.abc import Iterator, Sequence
from contextlib import contextmanager
from pathlib import Path
from typing import Final, Protocol, TextIO
import torch
_LAB_GPU_LOCK_ROOT: Final[Path] = Path("/tmp")
_BENCHMARK_GPU_LOCK_ROOT: Final[Path] = Path(
"/tmp/nnf_benchmark_gpu_locks"
)
_MINIMUM_GPU_HEADROOM_BYTES: Final[int] = 48 * 1024**3
class _ReleaseSolveModel(Protocol):
def solve(self, prompt: str) -> str:
"""Return the model-owned decoded response for one prompt."""
def _nvidia_identity_rows_boundary() -> tuple[tuple[str, int], ...]:
"""Read physical GPU UUIDs at the external host-discovery boundary."""
try:
completed = subprocess.run(
(
"nvidia-smi",
"--query-gpu=index,uuid",
"--format=csv,noheader,nounits",
),
check=True,
capture_output=True,
text=True,
)
except (FileNotFoundError, subprocess.SubprocessError):
return ()
rows: list[tuple[str, int]] = []
for line in completed.stdout.splitlines():
fields = tuple(part.strip() for part in line.split(",", maxsplit=1))
if len(fields) != 2 or not fields[0].isdigit() or not fields[1]:
continue
rows.append((fields[1], int(fields[0])))
return tuple(rows)
def _visible_physical_gpu_indices_boundary(
device_count: int,
) -> tuple[int, ...]:
"""Map process-local CUDA ordinals to physical lock-file identities."""
visible_text = os.environ.get("CUDA_VISIBLE_DEVICES")
if visible_text is None:
return tuple(range(device_count))
visible_tokens = tuple(
token.strip() for token in visible_text.split(",") if token.strip()
)
if (
not visible_tokens
or visible_tokens == ("-1",)
or len(visible_tokens) != device_count
):
return ()
identity_rows = (
()
if all(token.isdigit() for token in visible_tokens)
else _nvidia_identity_rows_boundary()
)
physical_indices: list[int] = []
for token in visible_tokens:
if token.isdigit():
physical_indices.append(int(token))
continue
matches = tuple(
physical_index
for uuid, physical_index in identity_rows
if uuid == token or uuid.startswith(token)
)
if len(matches) != 1:
return ()
physical_indices.append(matches[0])
if len(set(physical_indices)) != len(physical_indices):
return ()
return tuple(physical_indices)
def _try_acquire_gpu_locks_boundary(
physical_index: int,
) -> tuple[TextIO, TextIO] | None:
"""Acquire both standard exclusive GPU locks without waiting."""
_LAB_GPU_LOCK_ROOT.mkdir(parents=True, exist_ok=True)
_BENCHMARK_GPU_LOCK_ROOT.mkdir(parents=True, exist_ok=True)
paths = (
_LAB_GPU_LOCK_ROOT / f"nnf_gpu_{physical_index}.lock",
_BENCHMARK_GPU_LOCK_ROOT / f"gpu_{physical_index}.lock",
)
handles: list[TextIO] = []
try:
for path in paths:
handle = path.open("a+", encoding="utf-8")
try:
fcntl.flock(
handle.fileno(),
fcntl.LOCK_EX | fcntl.LOCK_NB,
)
except BlockingIOError:
handle.close()
return None
handles.append(handle)
finally:
if len(handles) != len(paths):
for cleanup_handle in reversed(handles):
fcntl.flock(cleanup_handle.fileno(), fcntl.LOCK_UN)
cleanup_handle.close()
return handles[0], handles[1]
def _release_gpu_locks_boundary(handles: tuple[TextIO, TextIO]) -> None:
for handle in reversed(handles):
fcntl.flock(handle.fileno(), fcntl.LOCK_UN)
handle.close()
@contextmanager
def _release_compute_lane_boundary(
*,
minimum_free_bytes: int = _MINIMUM_GPU_HEADROOM_BYTES,
) -> Iterator[torch.device]:
"""Hold one clean GPU lane for load and solve, or fall back to CPU."""
if isinstance(minimum_free_bytes, bool) or minimum_free_bytes < 1:
raise ValueError("Release 188 minimum GPU headroom must be positive")
if not torch.cuda.is_available():
yield torch.device("cpu")
return
device_count = torch.cuda.device_count()
physical_indices = _visible_physical_gpu_indices_boundary(device_count)
if len(physical_indices) != device_count:
yield torch.device("cpu")
return
candidates = tuple(
sorted(
(
(
torch.cuda.mem_get_info(local_index)[0],
physical_index,
local_index,
)
for local_index, physical_index in enumerate(physical_indices)
),
reverse=True,
)
)
for observed_free_bytes, physical_index, local_index in candidates:
if observed_free_bytes < minimum_free_bytes:
continue
handles = _try_acquire_gpu_locks_boundary(physical_index)
if handles is None:
continue
try:
free_bytes_after_lock = torch.cuda.mem_get_info(local_index)[0]
if free_bytes_after_lock < minimum_free_bytes:
continue
torch.cuda.set_device(local_index)
yield torch.device("cuda", local_index)
return
finally:
_release_gpu_locks_boundary(handles)
yield torch.device("cpu")
def _load_release_model_boundary(
release_path: Path,
*,
device: torch.device,
) -> _ReleaseSolveModel:
from resynthesis.release_model import load_release_188_model
return load_release_188_model(release_path, device=device)
def _parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="resynthesis",
description="Prompt Nucleus Resynthesis Release 188.",
)
commands = parser.add_subparsers(dest="command", required=True)
solve = commands.add_parser(
"solve",
help="Generate one model-owned response.",
)
solve.add_argument(
"--release",
required=True,
type=Path,
help="Path to runtime/model.json.",
)
solve.add_argument("prompt", help="Prompt text.")
return parser
def main(argv: Sequence[str] | None = None) -> int:
"""Run the minimal inference-only Release 188 command surface."""
arguments = _parser().parse_args(argv)
if arguments.command != "solve":
raise RuntimeError("Release 188 command dispatch differs")
release_path = arguments.release
prompt = arguments.prompt
if not isinstance(release_path, Path) or not isinstance(prompt, str):
raise RuntimeError("Release 188 solve arguments are malformed")
with _release_compute_lane_boundary() as device:
model = _load_release_model_boundary(
release_path,
device=device,
)
response = model.solve(prompt)
print(response)
return 0
if __name__ == "__main__":
raise SystemExit(main())
|