Signed-off-by: redearly123 <65453204+redearly123@users.noreply.github.com> Co-authored-by: redearly123 <65453204+redearly123@users.noreply.github.com>
125 lines
6.7 KiB
Markdown
125 lines
6.7 KiB
Markdown
# MammothModa2 startup benchmark
|
||
|
||
Measures `Omni()` initialization and first/subsequent image requests for
|
||
MammothModa2-Preview. This is a measurement baseline for
|
||
[#7075](https://github.com/vllm-project/vllm-omni/issues/7075); it changes no runtime code.
|
||
|
||
## Run
|
||
|
||
From the repository root, with the model downloaded and vLLM-Omni installed:
|
||
|
||
```bash
|
||
set -o pipefail
|
||
python benchmarks/mammoth_moda2/bench_startup.py \
|
||
--model /path/MammothModa2-Preview \
|
||
--deploy-config vllm_omni/deploy/mammoth_moda2.yaml \
|
||
--height 512 --width 512 --seed 42 \
|
||
--extra-body '{"text_guidance_scale": 4.0, "cfg_range": [0.0, 1.0], "num_inference_steps": 8}' \
|
||
--repeat 1 --label baseline --output-json baseline.json --save-image baseline.png \
|
||
2>&1 | tee baseline.log
|
||
python benchmarks/mammoth_moda2/parse_startup_log.py baseline.log --require-complete --markdown
|
||
```
|
||
|
||
Use `OMP_NUM_THREADS=16` to set CPU threads and `--parallel-stage-init` to
|
||
initialize stages concurrently. For first/subsequent requests, use
|
||
`--height 1024 --width 1024 --repeat 3` and 50 inference steps. Memory polling
|
||
is opt-in (`--sample-memory`); collect it in separate runs to avoid perturbing
|
||
the timing comparison. `--save-image` saves only the first request's image.
|
||
Compare that image across runs; a fixed seed alone does not guarantee equality
|
||
across execution modes or software versions.
|
||
|
||
## Measurement boundaries
|
||
|
||
| Metric | Boundary / limitation |
|
||
| --- | --- |
|
||
| Imports | Before torch import → benchmark imports complete; excludes interpreter startup |
|
||
| Time to ready | `Omni()` call → return; excludes client imports and requests |
|
||
| Time to first image | Benchmark clock start → first `generate()` return, including request setup |
|
||
| First / subsequent request | Each `generate()` call → return; same prompt and settings |
|
||
| Stage spawn / device init | Log timestamps: launch → `world_size=` → `Starting to load model`; 1 s resolution |
|
||
| Weight load | Engine-reported `Loading weights took`; read/cast/copy are merged |
|
||
| Model setup estimate | Reported model-load time minus weight-load time; not independently instrumented |
|
||
| Profile + KV + warmup | One merged interval after loading; compilation/capture may be nested within it |
|
||
| Compile / graph capture | Explicit engine log durations when present; N/A for eager execution |
|
||
| Memory | Optional 1 s samples: sum of process-tree RSS and maximum device memory used across GPUs reported by `nvidia-smi`; includes other GPU users and can miss transient peaks |
|
||
|
||
Stage timelines overlap with parallel initialization; do not sum them to
|
||
calculate time to ready. Missing log fields stay unmeasured. The parser marks
|
||
logs without `BENCH_JSON` as incomplete; `--require-complete` makes this an error.
|
||
|
||
## Reference results
|
||
|
||
A800-SXM4-80GB; Ubuntu 22.04; 16-CPU cgroup quota on a 128-core host;
|
||
vLLM 0.28.0+cu129, torch 2.13.0+cu129, vLLM-Omni `34aa1d2a`.
|
||
Checkpoint: 34.5 GiB, 8 shards, mostly fp32, on local NVMe.
|
||
Committed eager deploy config, GPU memory fractions 0.5 / 0.3.
|
||
|
||
The 2026-09-10 rerun used the corrected benchmark: one warm-up process,
|
||
then three rounds of four configurations with order rotated between rounds.
|
||
The checkpoint page cache was warmed before the matrix; no cache eviction
|
||
was requested during it. Each fresh process sent one 512×512, 8-step request
|
||
(guidance 4.0, seed 42). Memory polling was disabled. All 12 measured runs
|
||
are retained in [the results](reference_results.json).
|
||
Values below are `Omni()` seconds, mean ± sample standard deviation, n=3;
|
||
client imports took approximately another 10 s.
|
||
|
||
| CPU threads | Serial init | Parallel init |
|
||
| --- | --- | --- |
|
||
| Default (64) | 60.1 ± 0.2 | 41.1 ± 1.0 |
|
||
| 16 | 56.5 ± 0.9 | 36.7 ± 0.2 |
|
||
|
||
On this configuration, parallel initialization reduced time to ready by about
|
||
32%; combining it with 16 threads reduced it by about 39%. This supports
|
||
trying these settings on similar deployments, not changing defaults for all
|
||
models or hardware. Fixed 512×512 samples matched across all 12 measured runs;
|
||
this is a smoke check, not a broad quality evaluation.
|
||
|
||
For context, in the earlier serial baseline AR / DiT spent approximately 11 / 11 s in
|
||
spawn and imports, 6 / 6 s in device setup, 6 / 4 s loading weights, and
|
||
5 / 2 s in profile + KV + warmup. About 6 s followed the last stage becoming
|
||
ready. These coarse log intervals locate work; they are not independent
|
||
operator timings.
|
||
|
||
Separate observations from the earlier experiment (not rerun in this matrix):
|
||
|
||
- Requested page-cache eviction: 80.8 s; FlashInfer JIT cache removed:
|
||
129.1 s (means, n=3 each). These are separate cache conditions, not guaranteed
|
||
cold-machine startup or isolated disk/JIT costs.
|
||
- Three 1024×1024, 50-step eager requests in one process took
|
||
95.2 / 94.9 / 94.6 s. No large first-request penalty was observed in that run.
|
||
- With AR `enforce_eager: false` and serial init, time to ready was
|
||
62.5 ± 0.1 s (warm caches, n=3); logged graph capture was 4 s / 0.20 GiB.
|
||
The model reported torch.compile unsupported. KV capacity fell from about
|
||
15.7 to 2.0 GiB, and one parallel-init trial failed. The reported non-KV
|
||
profiling difference is not a measurement of graph allocation. Graph-mode
|
||
samples differed from eager. This needs separate memory and quality analysis
|
||
before recommending the configuration.
|
||
|
||
## Loading diagnostic and storage scenarios
|
||
|
||
```bash
|
||
OMP_NUM_THREADS=16 python benchmarks/mammoth_moda2/raw_load_bench.py \
|
||
--model /path/MammothModa2-Preview --shards 6,7,8 --mode cpu_cast
|
||
# Compare --mode gpu_cast in a fresh process with the same cache conditions.
|
||
|
||
MODEL_LOCAL=/local/MammothModa2-Preview OUT_DIR=./startup-bench \
|
||
bash benchmarks/mammoth_moda2/bench_storage_scenarios.sh
|
||
# Optional MODEL_NFS=/nfs/MammothModa2-Preview; SCENARIOS="local-cold local-warm".
|
||
```
|
||
|
||
The diagnostic clones each mmap-backed tensor into owned CPU memory before
|
||
casting. `materialize_s` includes page faults, CPU allocation and copying;
|
||
`cast_s` measures dtype conversion; `h2d_s` includes GPU allocation and copy.
|
||
CUDA context/operation warmup is outside the timer. Total also includes file
|
||
opening and bookkeeping. This extra CPU copy differs from the engine loader,
|
||
so these numbers do not decompose its loading time or measure disk bandwidth.
|
||
The revised diagnostic was run three times each for CPU cast with 64 / 16
|
||
threads and GPU cast with 16 threads; per-run values are in the results file.
|
||
Both CPU materialization and conversion were faster with 16 threads here; this
|
||
does not isolate how much of the engine-level improvement comes from either.
|
||
|
||
Storage scenarios explicitly read shards before warm runs and request
|
||
`posix_fadvise(DONTNEED)` before cold runs. Eviction is not guaranteed, and
|
||
server-side NFS caches are uncontrolled. The script stops on failure and
|
||
summarizes only logs from the current invocation.
|