Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions tensorrt_llm/_torch/pyexecutor/py_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6567,7 +6567,7 @@ def _warmup_encoder_cuda_graphs_enc_dec(self) -> None:
warmup(self.resource_manager)

def _submit_encoder_step(self, encoder_requests: List[LlmRequest]) -> None:
"""Queue encoder work, serializing it with decoder work under TP."""
"""Queue encoder work, joining the launch before the caller runs the decoder."""
executor = self.encoder_launch_executor
if executor is None:
raise RuntimeError("Encoder launch executor is unavailable.")
Expand Down Expand Up @@ -6603,8 +6603,18 @@ def _submit_encoder_step(self, encoder_requests: List[LlmRequest]) -> None:
self.inflight_req_ids.erase(request.request_id)
return

# torch.fx's tracing state is process-global, so a dynamo compile on
# either thread captures the other's concurrent module calls
# (https://nvbugs/6683840). Join the launch, but leave ready_event
# unsynchronized so encoder kernels still overlap decoder work.
try:
result = future.result()
except Exception as e:
self._finish_failed_encoder_step(requests, e)
return

self.pending_encoder_steps.append(
PendingEncoderStep(requests=requests, future=future))
PendingEncoderStep(requests=requests, future=future, result=result))

@nvtx_range("_poll_encoder_steps")
def _poll_encoder_steps(self) -> None:
Expand Down
8 changes: 5 additions & 3 deletions tests/unittest/_torch/executor/test_py_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,6 @@ def test_async_encoder_step_lifecycle():
ready_event=ready_event,
)
future = Mock()
future.done.side_effect = [False, True]
future.result.return_value = result
executor = _make_async_encoder_executor(future)
active_request = types.SimpleNamespace(
Expand All @@ -473,10 +472,13 @@ def test_async_encoder_step_lifecycle():
)
)

# The launch is joined inline (https://nvbugs/6683840); publication stays
# asynchronous, waiting on ready_event rather than the future.
executor._submit_encoder_step(requests)
executor._poll_encoder_steps()

future.result.assert_not_called()
future.result.assert_called_once_with()
future.done.assert_not_called()
ready_event.query.assert_not_called()
executor._publish_encoder_step.assert_not_called()
assert executor.inflight_req_ids.ids == {11, 12}
assert len(executor.pending_encoder_steps) == 1
Expand Down
Loading