[MSCCLPP-EP] Add C++ latency expert-parallel runtime - #895
[MSCCLPP-EP] Add C++ latency expert-parallel runtime#895Binyang Li (Binyang2014) wants to merge 9 commits into
Conversation
Add the public MoERuntime request API, latency dispatch/combine host runtime, and expert-major and rank-major CUDA kernels as a standalone mscclpp_ep library that does not depend on Python bindings. Preserve the unified throughput-facing API surface while rejecting throughput mode until its follow-up implementation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Callers can derive the topology distinction from isAvailable(), numRanks(), and numNvlRanks(); keep the initial C++ latency surface focused on the capability check. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove throughput-only prepare and notify methods and strip throughput request fields while retaining empty request types as placeholders for the follow-up implementation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the duplicate EP CUDA_CHECK macro with MSCCLPP_CUDATHROW and remove the unused throughput-only extended launch helper from the latency implementation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove unused device helpers, align helper naming and inline annotations with MSCCL++ conventions, cap latency routing at top-8, and keep rank-major combine on its TMA path without the unreachable fallback state. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cover latency runtime initialization, unsupported throughput requests, expert-major and rank-major dispatch/combine correctness across BF16 and FP8, and CUDA-graph D+C performance for 32 tokens per rank. Remove dead and redundant runtime state found during the kernel review. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use 100 graph replays to reduce variance in the expert-major and rank-major 32-token D+C measurements. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename the mode-owned host context types to LatencyRuntimeContext and ThroughputRuntimeContext, and clarify the combine input buffer documentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Rename the leader-only destination variable from completionRank to dstRank so the rank-major token-store path is easier to follow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run mscclpp-ut |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
| auto& context = *latencyContext_; | ||
| EP_HOST_ASSERT(context.available_); | ||
| EP_HOST_ASSERT(context.deviceContext_.devicePtr_ != nullptr); | ||
| EP_HOST_ASSERT(maxTokensPerRank > 0 && maxTokensPerRank <= context.maxTokensPerRank_); |
There was a problem hiding this comment.
Should we also validate numTokens <= maxTokensPerRank here, consistent with launchLatencyDispatch()?
| EP_HOST_ASSERT(mode == context.combineMode_); | ||
|
|
||
| LatencyStorageLayout allocationLayout(context.symmetricBuffer_, context.maxTokensPerRank_, hidden, context.numRanks_, | ||
| numExperts, numTopk, context.outputLayout_, context.combineMode_); |
There was a problem hiding this comment.
Are hidden, numExperts, and numTopk intended to vary between requests? I noticed they're specified both when constructing the runtime and in each request, and the request values don't appear to be required to match the runtime values
| EP_HOST_ASSERT(input == allocationLayout.combineRecvBuffer_); | ||
| } | ||
|
|
||
| const Workload workload{.epoch_ = context.epoch_, |
There was a problem hiding this comment.
Does combine need to validate that its workload parameters match the preceding dispatch? Since it reuses the dispatch routing metadata/epoch, I'm wondering what happens if numTokens or other workload parameters differ between the two calls.
|
|
||
| constexpr int NumRanks = 8; | ||
| constexpr int NumExperts = 8; | ||
| constexpr int NumTopk = 8; |
There was a problem hiding this comment.
Could we add a couple more routing configurations here. we can also do it in a separate PR.
-
A case with
NumExperts > NumTopk(for example, more experts per rank / a larger global expert count), since the currentNumExperts == NumTopk == 8means every token selects every expert. -
A nonuniform routing case where different experts receive different numbers of tokens, including potentially some experts receiving no tokens. This would help exercise the dispatch/combine paths under more realistic expert-load distributions.
| } | ||
|
|
||
| LatencyRuntimeContext::~LatencyRuntimeContext() noexcept(false) { | ||
| MSCCLPP_CUDATHROW(cudaDeviceSynchronize()); |
There was a problem hiding this comment.
Is the device-wide synchronization intentional here? cudaDeviceSynchronize() also waits for unrelated GPU work. Could we synchronize only the EP work before freeing the runtime resources?
| EP_HOST_ASSERT(symmetricBufferBytes_ % BufferAlignmentBytes == 0); | ||
| EP_HOST_ASSERT(maxTokensPerRank > 0); | ||
| EP_HOST_ASSERT(numExperts > 0 && numExperts % numRanks_ == 0); | ||
| EP_HOST_ASSERT(numTopk > 0 && numTopk <= MaxNumTopk); |
There was a problem hiding this comment.
Should we validate hidden against the supported latency hidden sizes here? The runtime allocates its buffers during construction, but unsupported hidden sizes are only rejected later when dispatch selects the kernel.
| /// Global expert count. | ||
| int numExperts; | ||
| /// Expert ID used for invalid rank-major entries. | ||
| int invalidTokenExpertId; |
There was a problem hiding this comment.
Could we document the expected value/range for invalidTokenExpertId?
Summary
MoERuntimeAPI and latency dispatch/combine request typesmscclpp_epshared library with no Python dependencyScope
ThroughputDispatchRequestandThroughputCombineRequesttypes reserve names for the follow-up implementationprepare,notify, host runtime, and CUDA kernels are intentionally excludedC++ test coverage
Validation
./tools/lint.shmscclpp_epbuilds forMSCCLPP_GPU_ARCHS=90andnativemscclpp_epandmscclpp_pylibmscclpp_ep.soand the public EP headersmpirun -np 8 ./build-ep-tests/bin/mp_unit_tests --filter=MoERuntimeTest: 4/4 passedFeature/EP regression comparison
feature/epaverages: expert-major 50.58 us, rank-major 41.21 us