from __future__ import annotations
import logging
import time
import torch
import torch.nn as nn
from ... import configure_vllm_logging, envs, model_prefetch
from ...load_strategy import (
LoadContext,
drain_tensor_readers,
publish_metadata,
run_load_strategy_chain,
unpublish_metadata,
)
from ...metrics import enable_metrics, metrics
from ...nixl_transfer import NixlTransferManager
from ...vmm.runtime import log_arena_post_load, maybe_enter_vmm_arena
from .adapter import _is_speculative_draft, build_vllm_load_context
from .artifacts import (
_vllm_health_ready,
install_vllm_cache_artifacts,
schedule_vllm_cache_artifact_publish,
)
from vllm.config import ModelConfig, VllmConfig
from vllm.config.load import LoadConfig
from vllm.model_executor.model_loader.base_loader import BaseModelLoader
from vllm.model_executor.model_loader.default_loader import DefaultModelLoader
from vllm.model_executor.model_loader.utils import initialize_model
from vllm.utils.torch_utils import set_default_torch_dtype
logger = logging.getLogger(__name__)
_tensor_registry: dict[int, dict[str, torch.Tensor]] = {}
_nixl_managers: dict[int, NixlTransferManager] = {}
_loader_registry: dict[int, MxModelLoader] = {}
def get_model_loader(device_id: int) -> MxModelLoader | None:
return _loader_registry.get(device_id)
class MxModelLoader(BaseModelLoader):
def __init__(self, load_config: LoadConfig):
super().__init__(load_config)
configure_vllm_logging()
enable_metrics()
self._ctx: LoadContext | None = None
def load_model(
self,
vllm_config: VllmConfig,
model_config: ModelConfig,
prefix: str = "",
) -> nn.Module:
load_start = time.perf_counter()
is_speculative_draft = _is_speculative_draft(vllm_config, model_config)
if is_speculative_draft and envs.MX_LOAD_STRATEGY_CHAIN == "RL":
raise ValueError(
"RL initial loading does not support speculative draft models"
)
ctx = build_vllm_load_context(vllm_config, model_config)
ctx.p2p_enabled = not is_speculative_draft
if envs.MX_ARTIFACT_READY_URL.strip():
ctx.source_ready_fn = lambda: _vllm_health_ready(ctx)
if ctx.p2p_enabled:
self._ctx = ctx
logger.info(
f"[Worker {ctx.global_rank}] MxModelLoader starting "
f"(model={ctx.identity.model_name}, p2p_enabled={ctx.p2p_enabled})"
)
model_role = "draft" if is_speculative_draft else "main"
model_id = ctx.identity.model_name
with metrics.time_load("vllm", model_id, model_role):
with maybe_enter_vmm_arena(ctx):
if ctx.p2p_enabled:
with metrics.time_load_phase("vllm", model_id, "artifact_install"):
install_vllm_cache_artifacts(ctx)
with set_default_torch_dtype(model_config.dtype):
with ctx.target_device:
with metrics.time_load_phase("vllm", model_id, "model_init"):
model = initialize_model(
vllm_config=vllm_config,
model_config=model_config,
prefix=prefix,
)
with metrics.time_load_phase("vllm", model_id, "chain"):
model = run_load_strategy_chain(model, ctx)
if ctx.p2p_enabled:
_loader_registry[ctx.device_id] = self
_tensor_registry[ctx.device_id] = ctx.tensors
if ctx.nixl_manager is not None:
_nixl_managers[ctx.device_id] = ctx.nixl_manager
else:
_nixl_managers.pop(ctx.device_id, None)
with metrics.time_load_phase("vllm", model_id, "publish"):
schedule_vllm_cache_artifact_publish(ctx)
log_arena_post_load(ctx)
total_time = time.perf_counter() - load_start
logger.info(
f"[Worker {ctx.global_rank}] MxModelLoader.load_model() COMPLETE "
f"in {total_time:.2f}s"
)
return model.eval()
def download_model(self, model_config: ModelConfig) -> None:
if envs.MX_LOAD_STRATEGY_CHAIN == "RL":
logger.info(
"RL initial load is selected; leaving weight acquisition to "
"the RL strategy chain"
)
return
if model_prefetch.is_enabled():
logger.info(
"MODEL_EXPRESS_NO_SHARED_STORAGE is set; leaving weight "
"acquisition to the ModelExpress strategy chain"
)
return
import copy
disk_config = copy.copy(self.load_config)
try:
disk_config.load_format = "auto"
except AttributeError:
object.__setattr__(disk_config, "load_format", "auto")
DefaultModelLoader(disk_config).download_model(model_config)
def load_weights(self, model: nn.Module, model_config: ModelConfig) -> None:
import copy
disk_config = copy.copy(self.load_config)
try:
disk_config.load_format = "auto"
except AttributeError:
object.__setattr__(disk_config, "load_format", "auto")
DefaultModelLoader(disk_config).load_weights(model, model_config)
@property
def nixl_manager(self) -> NixlTransferManager | None:
if self._ctx is not None:
return self._ctx.nixl_manager
return None
@property
def tensors(self) -> dict[str, torch.Tensor]:
if self._ctx is not None:
return self._ctx.tensors
return {}
@property
def worker_id(self) -> str | None:
if self._ctx is not None:
return self._ctx.worker_id
return None
def unpublish_runtime_tensors(self) -> None:
if self._ctx is not None:
drain_tensor_readers(
self._ctx,
timeout=envs.MX_TRANSFER_TIMEOUT,
)
unpublish_metadata(self._ctx)
def publish_runtime_tensors(self, version_id: str) -> None:
if self._ctx is not None:
self._ctx.identity.revision = version_id
publish_metadata(self._ctx)