Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c1bca71
Enable asynchronous adaptive MoE expert swaps
xadupre Oct 7, 2026
4a17f99
Track registered MoE expert count in kernel pilot
xadupre Oct 7, 2026
43f259a
Merge BF16 MoE offload into adaptive swaps
xadupre Oct 7, 2026
d5d615e
Merge branch 'moe-fp16-static-cpu-offload' into moe-fp16-async-expert…
xadupre Oct 7, 2026
8446c5f
Merge branch 'moe-fp16-static-cpu-offload' into moe-fp16-async-expert…
xadupre Oct 7, 2026
a0e25df
Document CUDA plugin swap limitation
xadupre Oct 7, 2026
a39be0c
Reuse MoE expert swap buffers
xadupre Oct 7, 2026
12ac220
Allow four concurrent MoE expert swaps
xadupre Oct 7, 2026
0e99479
Merge remote-tracking branch 'origin/moe-fp16-static-cpu-offload' int…
xadupre Oct 8, 2026
c552a6e
Expose MoE benchmark policy options
xadupre Oct 8, 2026
49ae47e
Select an available GPU for MoE benchmarks
xadupre Oct 8, 2026
e78972f
Merge branch 'moe-fp16-static-cpu-offload' into moe-fp16-async-expert…
xadupre Oct 9, 2026
d1d59f8
Merge latest static MoE offload fixes
xadupre Oct 9, 2026
2651343
Merge compact minimal-build validation
xadupre Oct 9, 2026
6fe9517
Pin Flash Attention in QMoE benchmarks
xadupre Oct 9, 2026
84752dc
Add model-wide MoE expert timeline analysis
xadupre Oct 9, 2026
46197ca
Improve cumulative MoE expert analysis plots
xadupre Oct 12, 2026
777903a
Add MoE counter parameter analysis
xadupre Oct 12, 2026
5de777b
Merge static MoE offload updates
xadupre Oct 12, 2026
1f51ef5
Configure MoE swap concurrency
xadupre Oct 12, 2026
66d19ae
Weight MoE popularity by routing probability
xadupre Oct 12, 2026
1eca8d4
Merge static MoE offload CI fix
xadupre Oct 12, 2026
b957bd9
Tune MoE swap policy defaults
xadupre Oct 12, 2026
819cfd8
Log MoE swap queue metrics
xadupre Oct 12, 2026
53aeb8d
Store only CPU-resident MoE experts
xadupre Oct 12, 2026
8ebc6c8
Log scheduled MoE expert swaps
xadupre Oct 12, 2026
5869447
Reduce MoE swap synchronization and defer compact CPU routing
xadupre Oct 13, 2026
db534c5
Integrate validated asynchronous CPU routing from static MoE base
xadupre Oct 13, 2026
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
38 changes: 25 additions & 13 deletions docs/moe-cpu-offload/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ Training, router changes, expert-weight quantization, and multiple CUDA devices
- [#32738](https://github.com/microsoft/onnxruntime/pull/32738) added the session-global expert state, CPU and CUDA
expert-selection collection, and exponentially decayed counters. It does not implement placement, CPU offload,
swaps, or redistribution.
- [#33039](https://github.com/microsoft/onnxruntime/pull/33039) added static FP16 CUDA `MoE` placement, hybrid
CPU/CUDA execution, and compact CUDA expert storage.
- The adaptive-swap implementation exchanges hot CPU experts with cold CUDA experts asynchronously while preserving
each node's CUDA slot count. Global slot redistribution across nodes remains future work.

## Exploratory routing analysis

Expand Down Expand Up @@ -61,7 +65,7 @@ The four numerical policy parameters are exposed as session configuration entrie
| `session.moe_cpu_offload_experts` | Offload count | Global number of experts to execute from CPU (`>= 0`); default `0`. |
| `session.moe_expert_counter_alpha` | `alpha` | Counter decay coefficient, finite and `>= 0`; default `0.9`. |
| `session.moe_expert_counter_beta` | `beta` | Increment for a used expert, finite and `>= 0`; default `0.1`. |
| `session.moe_expert_swap_epsilon` | `epsilon` | Relative swap margin, finite and `>= 0`. |
| `session.moe_expert_swap_epsilon` | `epsilon` | Relative swap margin, finite and `>= 0`; default `0`. |

The optional `session.moe_expert_counter_state_file` path is configured separately from these four numerical parameters.

Expand Down Expand Up @@ -288,20 +292,28 @@ must also be constant.

### Step 2: adaptive expert swaps

Implemented in the adaptive-swap change:

- Use the session-global counters and optional initial counter state to rank experts.
- Apply the strict `cpu_max > (1 + epsilon) * cuda_min` rule and let the pilot schedule exchanges after inference.
- Move the CUDA expert to CPU before moving its replacement to CUDA.
- Manage CUDA slots, two staging slots, two pinned buffers, dedicated device-to-host and host-to-device streams,
completion events, immutable per-invocation mappings, and atomic publication of completed swaps.
- Permit at most two in-flight exchanges per CUDA device and queue the rest.
- Pipeline the host-to-device transfer of one exchange with the device-to-host transfer of the other when the hardware
exposes bidirectional copy engines.
- Never wait for an incomplete exchange when a `MoE` starts; use the pre-exchange placement for that invocation.
- Redistribute the global CUDA expert budget after inference without draining pending exchanges, while maximizing the
number of completely CUDA-resident nodes.
- Test the epsilon boundary, transfer ordering, two-exchange concurrency, queued exchanges, nonblocking use of the old
mapping, asynchronous publication, global budget preservation, counter-based placement, and explicit transfer
failures.
- Move the CUDA expert to pinned CPU staging before moving its replacement to the extra CUDA slot.
- Use dedicated device-to-host and host-to-device streams, events, and separate staging allocations for each active
exchange.
- Permit at most two in-flight exchanges per CUDA device; additional eligible nodes are reconsidered at the next
inference boundary.
- Pipeline the host-to-device transfer of one exchange with the device-to-host transfer of another when the hardware
supports bidirectional copies.
- Never wait for an incomplete exchange when a `MoE` starts. The old placement remains published until transfer
completion; publication copies the staged expert into the persistent slot on that invocation's compute stream.
- Preserve each node's CUDA slot count and therefore the session-global CUDA expert budget.
- Test the strict epsilon boundary, deterministic tie-breaking, two-exchange concurrency, queued work, delayed
publication, and numerical parity before and after a swap.

Still planned:

- Redistribute CUDA slot ownership across nodes without draining pending exchanges, while maximizing the number of
completely CUDA-resident nodes.
- Add end-to-end throughput and memory measurements for representative Qwen models.

After these two implementation steps, the remaining work is end-to-end measurement. Run reproducible CPU-only,
CUDA-only, and hybrid evaluations with identical models, prompts, and generation settings; sweep offload targets and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ static const char* const kOrtSessionOptionsConfigMoeExpertCounterBeta =
static const char* const kOrtSessionOptionsConfigMoeCpuOffloadExperts =
"session.moe_cpu_offload_experts";

// Relative margin required before an adaptive MoE swap replaces a CUDA-resident expert.
// The value must be finite and non-negative. The default is 0.
static const char* const kOrtSessionOptionsConfigMoeExpertSwapEpsilon =
"session.moe_expert_swap_epsilon";

// A value of "1" means allocators registered in the env will be used. "0" means the allocators created in the session
// will be used. Use this to override the usage of env allocators on a per session level.
static const char* const kOrtSessionOptionsConfigUseEnvAllocators = "session.use_env_allocators";
Expand Down
Loading