main
py 83 lines 3.06 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 """Define EC connector functionality mixin for model runners."""
4
5 from collections.abc import Generator
6 from contextlib import AbstractContextManager, contextmanager, nullcontext
7 from typing import TYPE_CHECKING
8
9 import torch
10
11 from vllm.distributed.ec_transfer import get_ec_transfer, has_ec_transfer
12 from vllm.distributed.ec_transfer.ec_connector.base import ECConnectorBase
13 from vllm.logger import init_logger
14 from vllm.v1.outputs import ECConnectorOutput
15
16 if TYPE_CHECKING:
17 from vllm.v1.core.sched.output import SchedulerOutput
18
19 logger = init_logger(__name__)
20
21
22 # Defined as a EC connector functionality mixin for ModelRunner (GPU, TPU)
23 class ECConnectorModelRunnerMixin:
24 @staticmethod
25 def maybe_save_ec_to_connector(
26 encoder_cache: dict[str, torch.Tensor],
27 mm_hash: str,
28 ):
29 if not has_ec_transfer():
30 logger.debug("Not have ec transfer please check")
31 return
32 connector = get_ec_transfer()
33 connector.save_caches(encoder_cache=encoder_cache, mm_hash=mm_hash)
34
35 @staticmethod
36 def maybe_get_ec_connector_output(
37 scheduler_output: "SchedulerOutput",
38 encoder_cache: dict[str, torch.Tensor],
39 **kwargs,
40 ) -> AbstractContextManager[ECConnectorOutput | None]:
41 return (
42 ECConnectorModelRunnerMixin._get_ec_connector_output(
43 scheduler_output, encoder_cache, **kwargs
44 )
45 if has_ec_transfer()
46 else nullcontext()
47 )
48
49 # This context manager must be used within an active forward context.
50 # It encapsulates the entire EC connector lifecycle within execute_model
51 @staticmethod
52 @contextmanager
53 def _get_ec_connector_output(
54 scheduler_output: "SchedulerOutput",
55 encoder_cache: dict[str, torch.Tensor],
56 **kwargs,
57 ) -> Generator[ECConnectorOutput, None, None]:
58 output = ECConnectorOutput()
59
60 ec_connector = get_ec_transfer()
61 assert isinstance(ec_connector, ECConnectorBase)
62 assert scheduler_output.ec_connector_metadata is not None
63 ec_connector.bind_connector_metadata(scheduler_output.ec_connector_metadata)
64
65 if ec_connector.is_producer:
66 # Pass the cache explicitly: a producer needs it to publish an item
67 # that is already cached from an earlier step, which this step will
68 # not re-encode -- `save_caches` never fires for those.
69 ec_connector.start_save_caches(encoder_cache=encoder_cache, **kwargs)
70
71 # Load caches for consumer or both roles
72 if ec_connector.is_consumer:
73 ec_connector.start_load_caches(encoder_cache, **kwargs)
74
75 try:
76 yield output
77 finally:
78 output.finished_sending, output.finished_recving = (
79 ec_connector.get_finished(scheduler_output.finished_req_ids)
80 )
81 output.ec_connector_worker_meta = ec_connector.build_connector_worker_meta()
82
83 ec_connector.clear_connector_metadata()