Skip to content

[PoC] eplb experts exchange async - #14974

Closed
qiaoning13256 wants to merge 1 commit into
sgl-project:mainfrom
qiaoning13256:feat/eplb_experts_exchange_async
Closed

qiaoning13256 wants to merge 1 commit into
sgl-project:mainfrom
qiaoning13256:feat/eplb_experts_exchange_async

Conversation

@qiaoning13256

Copy link
Copy Markdown

Motivation

EPLB experts exchange synchronously will block main forward threads, and negative influence TTFT/TOPT p99.

Reference vLLM vllm-project/vllm#22179 we introduce a PoC solution.

Modifications

Accuracy Tests

Benchmarking and Profiling

Checklist

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @qiaoning13256, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a Proof of Concept solution to address performance bottlenecks caused by synchronous expert location updates in the EPLB (Expert Placement Load Balancing) system. By refactoring the update mechanism to be asynchronous, utilizing Python's generator capabilities and threading, the system can avoid blocking critical forward threads. This change also incorporates MUSA stream management for GPU operations and leverages specific MoE process groups for more efficient distributed communication, ultimately aiming to improve the overall responsiveness and tail latency of the system.

Highlights

  • Asynchronous Expert Exchange: The process of updating expert locations and weights is now performed asynchronously using Python threads and generators, preventing blocking of main forward threads.
  • Performance Improvement Target: This change aims to improve performance metrics like TTFT (Time To First Token) and TOPT (Time To Output Token) p99 by offloading synchronous operations.
  • MUSA Stream Integration: Expert weight updates are now executed within MUSA streams, indicating support for Huawei's Multi-GPU Architecture and leveraging its asynchronous capabilities for GPU operations.
  • Enhanced Distributed Communication: P2P communication for expert exchange explicitly utilizes a dedicated MoE (Mixture of Experts) process group, which can optimize distributed operations.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an asynchronous mechanism for expert weight exchange to improve performance, which is a valuable optimization. The changes are a good proof-of-concept, but there are a few critical issues and areas for improvement. I've identified two critical bugs where yield is used instead of yield from, which will break the asynchronous flow. Additionally, I've pointed out the use of global variables for thread communication, which is not robust and should be refactored. There is also some code duplication that could be cleaned up. Addressing these points will make the implementation more correct and maintainable.

Comment on lines +81 to 84
yield self._model_runner.update_expert_location(
expert_location_metadata,
update_layer_ids=update_layer_ids,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The update_expert_location method is now a generator. You should use yield from to delegate to it, instead of yield. Using yield will only yield the generator object itself, not its produced values, which will break the asynchronous execution flow.

Suggested change
yield self._model_runner.update_expert_location(
expert_location_metadata,
update_layer_ids=update_layer_ids,
)
yield from self._model_runner.update_expert_location(
expert_location_metadata,
update_layer_ids=update_layer_ids,
)

)
else:
self.expert_location_updater.update(
yield self.expert_location_updater.update(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The update method of expert_location_updater is a generator. You should use yield from to delegate to it. Using yield will only yield the generator object itself, which is not the intended asynchronous behavior.

Suggested change
yield self.expert_location_updater.update(
yield from self.expert_location_updater.update(

Comment on lines +126 to +127
async_ongoing = False
buffer2weight_copy_infos: List[Tuple[int, int]] = []

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using global variables async_ongoing and buffer2weight_copy_infos for communication between threads is not a robust design. It makes the code harder to reason about, test, and maintain, especially in a concurrent environment. Consider encapsulating the asynchronous update logic and its state within a class. This would avoid global state and provide a cleaner, more maintainable API.

For example:

class AsyncExpertUpdater:
    def __init__(self, ...):
        self.ongoing = False
        self.copy_infos = []
        # other necessary state

    def run(self):
        # logic from async_update
        ...

    def _update_worker(self):
        # logic from update_expert_weights_single_layer
        ...

Comment on lines +209 to +224
num_tensors = len(routed_experts_weights)
local_expert_location_range = (
rank * num_local_physical_experts,
(rank + 1) * num_local_physical_experts,
)

def _get_tensor(tensors, tensor_index: int, expert_location: int) -> torch.Tensor:
return tensors[tensor_index][_get_local_expert_location(expert_location)]

def _get_local_expert_location(expert_location: int) -> int:
assert (
local_expert_location_range[0]
<= expert_location
< local_expert_location_range[1]
)
return expert_location % num_local_physical_experts

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The helper functions _get_tensor and _get_local_expert_location and their surrounding logic are duplicated from update_expert_weights_single_layer_. This code duplication increases maintenance overhead. Please refactor this logic into a shared utility function or a helper class to avoid redundancy.

@github-actions

Copy link
Copy Markdown
Contributor

Thanks @qiaoning13256. Closing this because it is still a draft and has not been updated in 245 days.

Reopen it if the work is still relevant.

Some directories moved recently, so an older branch may need retargeting:
sgl-kernel/ -> python/sglang/kernels/aot/, python/sglang/jit_kernel/
-> python/sglang/kernels/jit/, docs/ -> docs/docs/ (.mdx),
bench_serving.py -> benchmark/serving.py, test/srt/ -> test/registered/.

@github-actions github-actions Bot closed this Aug 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant