Download inference/process.py from Rover00/WeMM-JEV: direct link, hf CLI and curl.
- Browser
- Download file 5.15 kB
-
https://huggingface.co/Rover00/WeMM-JEV/resolve/main/inference/process.py
- Command line
-
hf download hf://Rover00/WeMM-JEV/inference/process.py
-
curl -L -o process.py https://huggingface.co/Rover00/WeMM-JEV/resolve/main/inference/process.py
5.15 kB
| """Spawn one D3 process per GPU so FLA/Triton mutable state is not shared.""" | |
| import multiprocessing | |
| import threading | |
| import traceback | |
| from concurrent.futures import ProcessPoolExecutor | |
| from ._compat import Engine, NativeAbstention, Unsupported | |
| TARGET = f"{__package__}.engine:D3Engine" | |
| RUN_SEED = 20260919 | |
| _ENGINE = None | |
| _FAILURE = None | |
| _START_LOCK = threading.Lock() | |
| class WorkerError(RuntimeError): | |
| def __init__(self, record): | |
| super().__init__(record["error"]) | |
| self.exception_name = record["exception"] | |
| self.remote_traceback = record["traceback"] | |
| def _invoke(target, options, method, args, kwargs): | |
| global _ENGINE, _FAILURE | |
| if _FAILURE is not None: | |
| return False, _FAILURE | |
| try: | |
| if _ENGINE is None: | |
| from importlib import import_module | |
| if target == TARGET: | |
| import torch | |
| torch.manual_seed(RUN_SEED) | |
| module, name = target.split(":") | |
| _ENGINE = getattr(import_module(module), name)(**options) | |
| if method == "info": | |
| value = (_ENGINE.provenance, _ENGINE.runtime(), _ENGINE.latency) | |
| else: | |
| value = getattr(_ENGINE, method)(*args, **kwargs) | |
| if method == "__call__": | |
| _ENGINE.synchronize() | |
| return True, value | |
| except Exception as exc: | |
| record = {"error": str(exc), "exception": type(exc).__name__, | |
| "traceback": traceback.format_exc()} | |
| if isinstance(exc, NativeAbstention): | |
| record.update(kind="abstained", raw=exc.raw) | |
| elif isinstance(exc, Unsupported): | |
| record["kind"] = "unsupported" | |
| if _ENGINE is None or record["exception"] in ("OutOfMemoryError", "AcceleratorError") or "device-side assert" in str(exc): | |
| _FAILURE = record | |
| return False, record | |
| class _Child: | |
| def __init__(self, options, target=TARGET): | |
| self.options = options | |
| self.target = target | |
| self.lock = threading.Lock() | |
| self.pool = ProcessPoolExecutor(max_workers=1, mp_context=multiprocessing.get_context("spawn")) | |
| try: | |
| self.info = self.call("info") | |
| except BaseException: | |
| self.pool.shutdown(wait=True, cancel_futures=True) | |
| raise | |
| def call(self, method, *args, **kwargs): | |
| with self.lock: | |
| ok, value = self.pool.submit(_invoke, self.target, self.options, method, args, kwargs).result() | |
| if ok: | |
| return value | |
| if value.get("kind") == "unsupported": | |
| raise Unsupported(value["error"]) | |
| if value.get("kind") == "abstained": | |
| raise NativeAbstention(value["raw"]) | |
| raise WorkerError(value) | |
| def close(self): | |
| # Process exit releases the model and all CUDA allocations, even after an error. | |
| self.pool.shutdown(wait=True, cancel_futures=True) | |
| class D3ProcessEngine(Engine): | |
| name = "d3" | |
| def __init__(self, device=None, replicas=None, **options): | |
| import torch | |
| gpus = torch.cuda.device_count() if torch.cuda.is_available() else 0 | |
| if replicas is not None and int(replicas) > 1: | |
| if int(replicas) > gpus: | |
| raise ValueError(f"replicas={replicas} needs more than {gpus} CUDA devices") | |
| self.devices = [f"cuda:{i}" for i in range(int(replicas))] | |
| elif device in (None, "cuda"): | |
| self.devices = [f"cuda:{i}" for i in range(gpus)] or ["cpu"] | |
| else: | |
| self.devices = [str(device)] | |
| super().__init__(device=device, **options) | |
| self._options = options | |
| self._children = {} | |
| self._local = threading.local() | |
| self._lock = threading.Lock() | |
| self._next = 0 | |
| child = self._child(0) | |
| provenance, runtime, self.latency = child.info | |
| self.provenance = {**provenance, "gpu_execution": "one spawned process per GPU"} | |
| self._runtime = runtime | |
| def _child(self, slot): | |
| child = self._children.get(slot) | |
| if child is not None: | |
| return child | |
| with self._lock: | |
| if slot not in self._children: | |
| # Avoid simultaneous checkpoint loads exhausting host RAM. | |
| with _START_LOCK: | |
| self._children[slot] = _Child({**self._options, "device": self.devices[slot]}) | |
| return self._children[slot] | |
| def __call__(self, *args, **kwargs): | |
| slot = getattr(self._local, "slot", None) | |
| if slot is None: | |
| with self._lock: | |
| slot = self._next | |
| self._next = (self._next + 1) % len(self.devices) | |
| self._local.slot = slot | |
| return self._child(slot).call("__call__", *args, **kwargs) | |
| def warmup(self): | |
| self._child(0).call("warmup") | |
| def synchronize(self): | |
| for child in list(self._children.values()): | |
| child.call("synchronize") | |
| def runtime(self): | |
| return {**self._runtime, "gpu_execution": "spawn", "devices": self.devices} | |
| def close(self): | |
| for child in self._children.values(): | |
| child.close() | |
| self._children.clear() | |