Skip to content

Commit d918c8d

Browse files
committed
Add one-command B200 optimization suite
1 parent d98662e commit d918c8d

4 files changed

Lines changed: 218 additions & 10 deletions

File tree

README.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
A kernel-level exploration of **persistent expert-tile scheduling** and **workload-aware dispatch** for irregular Mixture-of-Experts (MoE) inference on NVIDIA Blackwell GPUs.
44

5-
> **Status:** Work in progress. The CUTLASS BF16 grouped baseline is validated on NVIDIA B200. An independent SM100a-native dense TMA/tcgen05/TMEM path is now implemented and awaiting its B200 correctness/performance gate.
5+
> **Status:** Work in progress. The CUTLASS BF16 grouped baseline is validated on NVIDIA B200. Direct CuTe, 1-SM/2-SM native collectives, and project-owned GPU scheduler probes compile for SM100a in CI and await their B200 correctness/performance gate.
66
77
## Motivation
88

@@ -140,9 +140,9 @@ All benchmark reports will record GPU model, clocks or power mode when relevant,
140140
- [x] Implement expert-tile decomposition and CPU scheduler simulation
141141
- [ ] Validate the SM100a one-SM TMA/tcgen05/TMEM dense kernel on B200
142142
- [ ] Validate the direct CuTe TMA/tcgen05/TMEM kernel on B200
143-
- [ ] Implement static persistent scheduling
144-
- [ ] Implement dynamic work distribution
145-
- [ ] Add active-expert compaction
143+
- [x] Implement and test static persistent GPU tile assignment
144+
- [x] Implement and test dynamic GPU work distribution with chunked claims
145+
- [x] Add active-expert compaction to the generated device work list
146146
- [ ] Evaluate CLC-assisted work redistribution
147147
- [ ] Profile scheduler overhead and CTA tail effects
148148
- [ ] Derive and validate the crossover dispatch model
@@ -230,4 +230,11 @@ See [`docs/sm100_native_dense.md`](docs/sm100_native_dense.md).
230230
- [x] Native dense correctness test and small-`M` CUDA Event benchmark
231231
- [x] Direct CuTe TMA barriers, TMEM allocation, tcgen05 MMA, and TMEM-load epilogue
232232
- [x] Direct CuTe CPU-reference correctness test and benchmark harness
233-
- [ ] Project-owned device-side expert-tile persistent schedulers
233+
- [x] Two-SM TMA-multicast/tcgen05 collective reference and benchmark
234+
- [x] Project-owned device-side expert-tile persistent schedulers
235+
- [x] Exact-once GPU scheduler correctness and observed CTA-load metrics
236+
237+
Run the complete native-kernel and scheduler matrix with
238+
[`tools/run_b200_optimization_suite.sh`](tools/run_b200_optimization_suite.sh).
239+
The output boundary and interpretation are documented in
240+
[`docs/b200_optimization_suite.md`](docs/b200_optimization_suite.md).

benchmarks/sm100_2sm_benchmark.cu

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,15 +182,18 @@ int main(int argc, char** argv) {
182182
(median_ms * 1.0e9);
183183
const auto stats = plan.stats();
184184
if (options.csv) {
185-
std::cout << "kernel,device,cuda_runtime,cutlass,m,n,k,median_ms,p95_ms,"
186-
"tflops,tile_m,tile_n,tile_k,persistent_ctas,workspace_bytes\n"
185+
std::cout << "kernel,device,compute_capability,cuda_runtime,cutlass,m,n,k,"
186+
"warmup,iterations,median_ms,p95_ms,tflops,tile_m,tile_n,"
187+
"tile_k,sm_count,persistent_ctas,workspace_bytes\n"
187188
<< sm100_2sm_kernel_name() << ',' << properties.name << ','
189+
<< properties.major << '.' << properties.minor << ','
188190
<< runtime_version << ',' << BLACKWELL_MOE_CUTLASS_REVISION
189191
<< ',' << options.m << ',' << options.n << ',' << options.k
190-
<< ',' << median_ms << ',' << p95_ms << ',' << tflops << ','
192+
<< ',' << options.warmup << ',' << options.iterations << ','
193+
<< median_ms << ',' << p95_ms << ',' << tflops << ','
191194
<< stats.tile_m << ',' << stats.tile_n << ',' << stats.tile_k
192-
<< ',' << stats.persistent_ctas << ',' << stats.workspace_bytes
193-
<< '\n';
195+
<< ',' << stats.sm_count << ',' << stats.persistent_ctas << ','
196+
<< stats.workspace_bytes << '\n';
194197
} else {
195198
std::cout << "kernel=" << sm100_2sm_kernel_name()
196199
<< " shape=" << options.m << 'x' << options.n << 'x'

docs/b200_optimization_suite.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# B200 Optimization Suite
2+
3+
This suite separates three questions that must not be collapsed into one
4+
speedup number:
5+
6+
1. Does each kernel produce correct output on SM100a?
7+
2. Which Blackwell math pipeline is best for a given dense expert shape?
8+
3. Does dynamic expert-tile assignment recover enough load balance to pay for
9+
its queue overhead?
10+
11+
## Implemented paths
12+
13+
| Path | Purpose | Blackwell mechanisms |
14+
| --- | --- | --- |
15+
| CUTLASS grouped baseline | Irregular MoE reference | Portable grouped GEMM |
16+
| 1-SM collective | Optimized native reference | TMA, auto-staged warp specialization, tcgen05, TMEM, TMA epilogue, persistent CLC |
17+
| 2-SM collective | Cooperative native reference | 2-SM tcgen05, TMA multicast, auto-staged warp specialization, TMEM, persistent CLC |
18+
| Direct CuTe | Inspectable teaching kernel | Explicit TMA barriers, TMEM allocation, tcgen05 MMA, TMEM-to-register load |
19+
| Scheduler probe | Project-owned policy experiment | Persistent CTAs, static assignment, atomic dynamic queue, chunked claims |
20+
21+
The scheduler probe intentionally uses deterministic integer work proportional
22+
to `valid_m * valid_n`; it does not execute GEMM. Its latency measures queue and
23+
load-balancing behavior in isolation. It must not be reported as a GEMM
24+
speedup. The native collective benchmarks measure the math pipeline, while a
25+
later integration combines project-owned expert-tile acquisition with that
26+
pipeline.
27+
28+
## Build
29+
30+
```bash
31+
cmake -S . -B build-gpu-make -G "Unix Makefiles" \
32+
-DCMAKE_BUILD_TYPE=Release \
33+
-DBLACKWELL_MOE_ENABLE_CUDA=ON \
34+
-DBLACKWELL_MOE_ENABLE_SM100_NATIVE=ON \
35+
-DBLACKWELL_MOE_CUDA_ARCHITECTURES=100 \
36+
-DBLACKWELL_MOE_BUILD_TESTS=ON
37+
38+
cmake --build build-gpu-make -j "$(nproc)"
39+
```
40+
41+
The native translation units are compiled for `compute_100a/sm_100a`; the
42+
architecture-accelerated suffix is required for tcgen05 and TMEM.
43+
44+
## Run everything once
45+
46+
```bash
47+
./tools/run_b200_optimization_suite.sh \
48+
build-gpu-make \
49+
results/b200-optimization-suite
50+
```
51+
52+
For a cheaper smoke run before the full matrix:
53+
54+
```bash
55+
BLACKWELL_MOE_WARMUP=5 BLACKWELL_MOE_ITERATIONS=20 \
56+
./tools/run_b200_optimization_suite.sh \
57+
build-gpu-make \
58+
results/b200-optimization-smoke
59+
```
60+
61+
The script runs all correctness tests first and stops on the first failure. It
62+
then writes:
63+
64+
- `environment.txt`: GPU, driver, CUDA, and CMake metadata;
65+
- `correctness.log`: CPU, grouped-GEMM, scheduler, and SM100a gates;
66+
- `grouped_baseline.csv`: routing-distribution baseline;
67+
- `native_1sm_vs_2sm.csv`: 1-SM/2-SM crossover sweep;
68+
- `direct_cute.csv`: explicit primitive path;
69+
- `scheduler_probe.csv`: static/dynamic and claim-size sweep;
70+
- a compressed `.tar.gz` archive next to the result directory.
71+
72+
## How to read the scheduler rows
73+
74+
- `median_ms` and `p95_ms` include the probe kernel but exclude host workload
75+
generation and the queue reset.
76+
- `observed_cta_work_cv` is measured from device counters after execution.
77+
- `tail_ratio = max(CTA work) / mean(CTA work)`; lower is better.
78+
- `observed_utilization = mean(CTA work) / max(CTA work)`; higher is better.
79+
- `claim_size=1` maximizes adaptability and atomic traffic; larger chunks
80+
amortize atomics but can reintroduce tail imbalance.
81+
82+
The desired result is a crossover, not a universal winner. Uniform workloads
83+
should expose dynamic-queue overhead. Heavy-hitter and Zipf workloads should
84+
show whether reduced tail imbalance compensates for that overhead. Sparse
85+
workloads additionally test active-expert compaction because zero-token experts
86+
produce no device work items.
87+
88+
## Runtime validation boundary
89+
90+
GitHub Actions compile every CUDA target for `sm_100a` in an official CUDA 13
91+
development container, but Actions do not provide a B200. A green CI check
92+
therefore proves compilation only. Correctness, latency, generated SASS, and
93+
performance-counter claims remain unvalidated until this suite runs on B200.
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
build_dir="${1:-build-gpu-make}"
5+
results_dir="${2:-results/b200-optimization-suite}"
6+
warmup="${BLACKWELL_MOE_WARMUP:-20}"
7+
iterations="${BLACKWELL_MOE_ITERATIONS:-200}"
8+
9+
mkdir -p "${results_dir}"
10+
11+
append_csv() {
12+
local output="$1"
13+
shift
14+
local temporary
15+
temporary="$(mktemp)"
16+
"$@" --csv >"${temporary}"
17+
if [[ ! -s "${output}" ]]; then
18+
cp "${temporary}" "${output}"
19+
else
20+
tail -n +2 "${temporary}" >>"${output}"
21+
fi
22+
rm "${temporary}"
23+
}
24+
25+
for binary in \
26+
test_cutlass_correctness \
27+
test_scheduler_probe \
28+
test_sm100_dense_correctness \
29+
test_sm100_2sm_correctness \
30+
test_direct_cute_correctness \
31+
moe_gpu_bench \
32+
moe_scheduler_gpu_bench \
33+
sm100_dense_bench \
34+
sm100_2sm_bench \
35+
direct_cute_bench; do
36+
if [[ ! -x "${build_dir}/${binary}" ]]; then
37+
echo "missing executable: ${build_dir}/${binary}" >&2
38+
echo "configure with BLACKWELL_MOE_ENABLE_CUDA=ON and " \
39+
"BLACKWELL_MOE_ENABLE_SM100_NATIVE=ON, then rebuild" >&2
40+
exit 1
41+
fi
42+
done
43+
44+
{
45+
date -u
46+
nvidia-smi --query-gpu=name,driver_version,memory.total,power.limit \
47+
--format=csv,noheader
48+
nvcc --version
49+
cmake --version
50+
} >"${results_dir}/environment.txt"
51+
52+
ctest --test-dir "${build_dir}" --output-on-failure \
53+
2>&1 | tee "${results_dir}/correctness.log"
54+
55+
baseline_csv="${results_dir}/grouped_baseline.csv"
56+
: >"${baseline_csv}"
57+
for distribution in uniform heavy_hitter sparse zipf; do
58+
append_csv "${baseline_csv}" "${build_dir}/moe_gpu_bench" \
59+
"--distribution=${distribution}" \
60+
--experts=64 --tokens=4096 --n=7168 --k=2048 \
61+
"--warmup=${warmup}" "--iterations=${iterations}"
62+
done
63+
64+
native_csv="${results_dir}/native_1sm_vs_2sm.csv"
65+
: >"${native_csv}"
66+
for m in 128 256 512 1024 4096 8192; do
67+
append_csv "${native_csv}" "${build_dir}/sm100_dense_bench" \
68+
"--m=${m}" --n=7168 --k=2048 \
69+
"--warmup=${warmup}" "--iterations=${iterations}"
70+
append_csv "${native_csv}" "${build_dir}/sm100_2sm_bench" \
71+
"--m=${m}" --n=7168 --k=2048 \
72+
"--warmup=${warmup}" "--iterations=${iterations}"
73+
done
74+
75+
direct_csv="${results_dir}/direct_cute.csv"
76+
: >"${direct_csv}"
77+
for m in 128 256 512 1024; do
78+
append_csv "${direct_csv}" "${build_dir}/direct_cute_bench" \
79+
"--m=${m}" --n=7168 --k=2048 \
80+
"--warmup=${warmup}" "--iterations=${iterations}"
81+
done
82+
83+
scheduler_csv="${results_dir}/scheduler_probe.csv"
84+
: >"${scheduler_csv}"
85+
for distribution in uniform heavy_hitter sparse zipf; do
86+
append_csv "${scheduler_csv}" "${build_dir}/moe_scheduler_gpu_bench" \
87+
"--distribution=${distribution}" --scheduler=static \
88+
--experts=64 --tokens=4096 --n=7168 --tile-m=128 --tile-n=128 \
89+
--ctas=120 --claim-size=1 --work-scale=8 \
90+
"--warmup=${warmup}" "--iterations=${iterations}"
91+
for claim_size in 1 2 4 8; do
92+
append_csv "${scheduler_csv}" "${build_dir}/moe_scheduler_gpu_bench" \
93+
"--distribution=${distribution}" --scheduler=dynamic \
94+
--experts=64 --tokens=4096 --n=7168 --tile-m=128 --tile-n=128 \
95+
--ctas=120 "--claim-size=${claim_size}" --work-scale=8 \
96+
"--warmup=${warmup}" "--iterations=${iterations}"
97+
done
98+
done
99+
100+
tar -czf "${results_dir}.tar.gz" -C "$(dirname "${results_dir}")" \
101+
"$(basename "${results_dir}")"
102+
103+
echo "B200 optimization suite complete"
104+
echo "results: ${results_dir}"
105+
echo "archive: ${results_dir}.tar.gz"

0 commit comments

Comments
 (0)