# SGLang TP×DP Matrix Benchmark Benchmark SGLang inference performance across different Tensor Parallelism (TP) × Data Parallelism (DP) configurations for large MoE models (e.g., DeepSeek-V4-Flash). ## What This Experiment Does This experiment systematically tests how different parallel strategies affect serving performance: | Config | TP | DP | GPUs per replica | Replicas | |--------|----|----|------------------|----------| | tp2_dp4 | 2 | 4 | 2 | 4 | | tp4_dp2 | 4 | 2 | 4 | 2 | | tp8_dp1 | 8 | 1 | 8 | 1 | For each configuration, it runs a matrix of input/output sequence lengths and concurrency levels, measuring: - **TTFT** (Time To First Token) - **TPOT** (Time Per Output Token) - **Throughput** (requests/s, output tokens/s) - **GPU memory usage** - **SLO compliance** (TTFT P95 < 3000ms, TPOT mean < 50ms) ## Quick Start ### 1. Prerequisites - NVIDIA GPU server with Docker and NVIDIA Container Toolkit - Model weights mounted locally (e.g., `/data/models/DeepSeek-V4-Flash`) - ShareGPT-format dataset JSON for the random sampler (e.g., `/data/datasets/ShareGPT_V4.3_unfiltered_cleaned_split.json`) - SGLang Docker image pulled locally ### 2. Configure the Experiment Edit `config.env` to match your environment: ```bash # Model settings MODEL_NAME="DeepSeek-V4-Flash" MODEL_PATH="/data/models/DeepSeek-V4-Flash" SERVED_MODEL_NAME="deepseek-v4-flash" # Docker image (change this if you use a custom or private registry image) DOCKER_IMAGE="lmsysorg/sglang:latest" # Dataset path (change this to your local dataset) DATASET_PATH="/data/datasets/ShareGPT_V4.3_unfiltered_cleaned_split.json" # GPU devices to use CUDA_VISIBLE_DEVICES="0,1,2,3,4,5,6,7" # TP×DP configurations to test PARALLEL_CONFIGS=( "2 4" "4 2" "8 1" ) ``` ### 3. Run the Experiment #### Option A: Persistent Container Mode (Recommended) Starts a long-running container and reuses it across configurations. This avoids reloading the model and preserves DeepGEMM JIT cache, saving significant time. ```bash # Step 1: Start the persistent container (run once) bash start_sglang_container.sh # Step 2: Run the benchmark CONTAINER_NAME="dsv4_h200_sglang_tp_dp_matrix_sglang_container" \ bash run_bench.sh ``` #### Option B: One-Container-Per-Config Mode Each TP×DP configuration starts a fresh Docker container. Slower but simpler. ```bash # Just run the main script bash run_bench.sh ``` ### 4. View Results Results are saved under `results//`: ``` results/ └── full_20260710-063109/ ├── tp2_dp4/ │ ├── results.json # Parsed metrics per scenario │ ├── raw_outputs/ # Raw benchmark output files │ ├── gpu_logs/ # GPU memory CSV logs │ └── logs/ # Detailed logs per scenario ├── tp4_dp2/ │ └── ... ├── tp8_dp1/ │ └── ... ├── comparison.md # Cross-config comparison report └── logs/ └── orchestrator.log # Main experiment log ``` Generate the comparison report manually: ```bash python3 compare.py --run-root results/ --output results//comparison.md ``` ## Configuration Reference ### `config.env` — Main Configuration File | Variable | Default | Description | |----------|---------|-------------| | `MODEL_NAME` | `DeepSeek-V4-Flash` | Human-readable model name | | `MODEL_PATH` | `/data/models/DeepSeek-V4-Flash` | **Local path to model weights** | | `SERVED_MODEL_NAME` | `deepseek-v4-flash` | Model name exposed by the server | | `DOCKER_IMAGE` | `lmsysorg/sglang:latest` | **SGLang Docker image** | | `DATASET_PATH` | `/data/datasets/ShareGPT_V4.3_unfiltered_cleaned_split.json` | **Local dataset for random sampler** | | `CUDA_VISIBLE_DEVICES` | `0,1,2,3,4,5,6,7` | GPU devices to use | | `PARALLEL_CONFIGS` | `("2 4" "4 2" "8 1")` | TP×DP configurations to test | | `CONTEXT_LENGTH` | `1048576` | Max context length (tokens) | | `MAX_RUNNING_REQUESTS` | `128` | Max concurrent requests | | `MEM_FRACTION_STATIC` | `0.88` | Static memory fraction | | `MOE_RUNNER_BACKEND` | `marlin` | MoE backend (marlin, flashinfer, etc.) | | `USE_DOCKER` | `1` | Run server in Docker (1) or native venv (0) | | `USE_DOCKER_CLIENT` | `1` | Run benchmark client in Docker (1) or native (0) | | `SGLANG_PORT` | `30031` | Server port | | `MATRIX_FILE` | `matrix.json` | Scenario matrix definition | | `MATRIX_MODE` | `Y` | Test only Y (mandatory), or Y+P (include optional) | | `CONCURRENCY_SAMPLES` | `2` | Concurrency sampling density | | `SCENARIO_TIMEOUT_S` | `1800` | Per-scenario timeout (seconds) | | `DRY_RUN` | `0` | If 1, only print plan without running | | `GRID_LIMIT` | `0` | Limit scenarios per config (0 = all) | ### `matrix.json` — Test Scenario Matrix Defines which (Input Sequence Length, Output Sequence Length) combinations to test: ```json { "mode": "Y", "matrix": { "1024": { "128": "Y", "256": "Y", ... }, "4096": { "128": "Y", "256": "Y", ... } }, "concurrency": { "1024": { "low": 1, "high": 128 }, "4096": { "low": 1, "high": 64 } } } ``` Mark meanings: - **Y** = Must test; failure stops the config - **P** = Optional; failure is recorded but continues - **N** = Skip ### `smoke_matrix.json` — Quick Verification Small matrix for fast testing. Use it to verify the setup works: ```bash MATRIX_FILE="${PWD}/smoke_matrix.json" \ GRID_LIMIT=4 \ bash run_bench.sh ``` ## Script Reference | Script | Purpose | When to Run | |--------|---------|-------------| | `run_bench.sh` | **Main experiment orchestrator** | Always run this | | `start_sglang_container.sh` | Start a persistent Docker container | Before run_bench.sh if using persistent mode | | `run_sglang_in_container.sh` | Start/restart server inside persistent container | Called by run_bench.sh | | `start_sglang_dp.sh` | Entry point for starting server | Called by run_bench.sh | | `start_sglang_docker.sh` | Start a fresh Docker container per config | Called by start_sglang_dp.sh | | `generate_scenarios.py` | Generate scenario TSV from matrix.json | Called by run_bench.sh | | `compare.py` | Generate cross-config comparison report | Called by run_bench.sh, or run manually | ## Migrating to a New Server When moving this experiment to a different server, update these fields in `config.env`: 1. **Model path**: `MODEL_PATH` → your local model weights directory 2. **Docker image**: `DOCKER_IMAGE` → your SGLang image (e.g., `myregistry/sglang:v0.4.0`) 3. **Dataset path**: `DATASET_PATH` → your local ShareGPT-format JSON 4. **GPU devices**: `CUDA_VISIBLE_DEVICES` → match your hardware 5. **TP×DP configs**: `PARALLEL_CONFIGS` → adjust to your GPU count - Total GPUs must equal `TP × DP` for each config - Example: 8 GPUs → `(2 4)`, `(4 2)`, `(8 1)` are all valid Optional adjustments: - `CONTEXT_LENGTH` → model's max context length - `MEM_FRACTION_STATIC` → adjust if you hit OOM - `MOE_RUNNER_BACKEND` → `marlin`, `flashinfer`, etc. ## Troubleshooting | Symptom | Cause | Fix | |---------|-------|-----| | `docker: invalid reference format` | `DOCKER_IMAGE` not exported to subshell | Already fixed; ensure `run_bench.sh` exports it | | Server health check timeout | Model loading takes >20 min | Increase wait loops in `start_sglang_docker.sh` or use persistent container mode | | `CUDA out of memory` | Config exceeds GPU memory | Reduce `MEM_FRACTION_STATIC` or test smaller ISL/DSL | | Benchmark client can't reach server | Network isolation | Ensure both server and client use `--network host` | | Stale container from previous run | Container name collision | `docker rm -f ` before restarting | ## Monitoring a Running Experiment ```bash # Watch the main log tail -f /tmp/full_experiment.log # Check if the orchestrator is still running ps aux | grep run_bench | grep -v grep # Check GPU utilization watch -n 1 nvidia-smi # Check server health curl http://127.0.0.1:30031/health ``` ## Output Files - `results///results.json` — Parsed metrics per scenario - `results///raw_outputs/` — Raw `sglang.bench_serving` JSONL output - `results///gpu_logs/` — GPU memory usage CSV - `results//comparison.md` — Side-by-side comparison across all configs - `results//skipped_after_oom.csv` — Record of OOM/failed scenarios ## License Follows the project's existing license. Model weights and Docker images are subject to their respective licenses.