Signed-off-by: roG0d <baonudesifeizhai@gmail.com> Signed-off-by: baonudesifeizhai <85092850+baonudesifeizhai@users.noreply.github.com>
238 lines
7.2 KiB
Markdown
238 lines
7.2 KiB
Markdown
# Qwen-Image
|
|
|
|
> Text-to-image serving with optional step-wise continuous batching
|
|
|
|
## Summary
|
|
|
|
- Vendor: Qwen
|
|
- Model: `Qwen/Qwen-Image`
|
|
- Task: Text-to-image generation
|
|
- Mode: Online serving with optional step-wise continuous batching
|
|
- Maintainer: Community
|
|
|
|
## When to use this recipe
|
|
|
|
Use this recipe when you want a known-good starting point for serving
|
|
`Qwen/Qwen-Image` on a single 80 GB A100, validate the normal online-serving
|
|
path, and optionally replay the benefit of step-wise continuous batching with
|
|
the benchmark assets already bundled in this repository.
|
|
|
|
## References
|
|
|
|
- Upstream or canonical docs:
|
|
[`docs/user_guide/examples/online_serving/text_to_image.md`](../../docs/user_guide/examples/online_serving/text_to_image.md)
|
|
- Related example under `examples/`:
|
|
[`examples/online_serving/text_to_image/README.md`](../../examples/online_serving/text_to_image/README.md)
|
|
- Related benchmark:
|
|
[`benchmarks/diffusion/diffusion_benchmark_serving.py`](../../benchmarks/diffusion/diffusion_benchmark_serving.py)
|
|
|
|
## Hardware Support
|
|
|
|
This recipe currently documents one CUDA GPU serving configuration. Extend it
|
|
with more hardware sections as community validation lands.
|
|
|
|
## GPU
|
|
|
|
### 1x A100 80GB
|
|
|
|
#### Environment
|
|
|
|
- OS: Linux
|
|
- Python: 3.10+
|
|
- Driver / runtime: NVIDIA CUDA environment with an A100 80 GB GPU
|
|
- vLLM version: Match the repository requirements for your checkout
|
|
- vLLM-Omni version or commit: Use the commit you are deploying from
|
|
|
|
#### Command
|
|
|
|
Start the baseline server:
|
|
|
|
```bash
|
|
vllm serve Qwen/Qwen-Image --omni --port 8091
|
|
```
|
|
|
|
To enable the step-wise runtime without batching:
|
|
|
|
```bash
|
|
vllm serve Qwen/Qwen-Image --omni \
|
|
--port 8091 \
|
|
--step-execution \
|
|
--max-num-seqs 1
|
|
```
|
|
|
|
To enable experimental compatible-request batching:
|
|
|
|
```bash
|
|
vllm serve Qwen/Qwen-Image --omni \
|
|
--port 8091 \
|
|
--step-execution \
|
|
--max-num-seqs 8
|
|
```
|
|
|
|
You can also use the example launcher and pass the extra flags through:
|
|
|
|
```bash
|
|
bash examples/online_serving/text_to_image/run_server.sh --step-execution --max-num-seqs 8
|
|
```
|
|
|
|
#### Verification
|
|
|
|
Run the existing client example after the server is ready:
|
|
|
|
```bash
|
|
python examples/online_serving/text_to_image/openai_chat_client.py \
|
|
--server http://localhost:8091 \
|
|
--prompt "A ceramic teapot on a wooden table" \
|
|
--output /tmp/qwen_image_recipe.png
|
|
```
|
|
|
|
For a direct API smoke test:
|
|
|
|
```bash
|
|
curl http://localhost:8091/v1/images/generations \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"model": "Qwen/Qwen-Image",
|
|
"prompt": "A ceramic teapot on a wooden table",
|
|
"size": "1024x1024",
|
|
"num_inference_steps": 20,
|
|
"seed": 42
|
|
}'
|
|
```
|
|
|
|
To replay the batching benefit with matched warmup:
|
|
|
|
```bash
|
|
python benchmarks/diffusion/diffusion_benchmark_serving.py \
|
|
--endpoint /v1/chat/completions \
|
|
--dataset vbench \
|
|
--task t2i \
|
|
--model Qwen/Qwen-Image \
|
|
--num-prompts 10 \
|
|
--height 1024 \
|
|
--width 1024 \
|
|
--num-inference-steps 50 \
|
|
--seed 42 \
|
|
--port 8089 \
|
|
--max-concurrency 8 \
|
|
--warmup-requests 8 \
|
|
--warmup-concurrency 8 \
|
|
--warmup-num-inference-steps 3 \
|
|
--disable-tqdm
|
|
```
|
|
|
|
Run that once against `--max-num-seqs 1`, then rerun it against `--max-num-seqs 8`
|
|
and compare the output JSON or terminal metrics.
|
|
|
|
#### Notes
|
|
|
|
- Memory usage: keep headroom for first-request compile and image decode overhead.
|
|
- Key flags: `--step-execution` enables the step-wise runtime; `--max-num-seqs` controls how many compatible requests may stay active together.
|
|
- Keep `--max-num-seqs 1` when you want the more conservative path, when traffic is mostly single-request, or when you are debugging correctness before measuring throughput.
|
|
- Current batching is still shape-sensitive: different step progress can co-batch, but different resolutions do not yet co-batch.
|
|
|
|
### 2x B200 ModelOpt mixed FP8/NVFP4
|
|
|
|
#### Environment
|
|
|
|
- OS: Linux
|
|
- Python: 3.12
|
|
- Driver / runtime: NVIDIA CUDA environment with two B200 GPUs
|
|
- vLLM version: Match the vLLM-Omni checkout used for deployment
|
|
- vLLM-Omni version or commit: Use the commit that contains ModelOpt mixed
|
|
FP8/NVFP4 checkpoint loading for diffusion models
|
|
|
|
#### Command
|
|
|
|
This configuration uses a pre-quantized ModelOpt mixed checkpoint for
|
|
Qwen-Image-2512. The validated checkpoint keeps boundary, modulation,
|
|
normalization, and output layers in BF16, uses FP8 for sensitive attention
|
|
projections, and uses NVFP4 for heavier MLP / attention-output linear layers.
|
|
|
|
Validated checkpoint:
|
|
|
|
```text
|
|
feizhai123/qwen-image-2512-modelopt-mixed-fp8-sensitive-nvfp4-heavy
|
|
```
|
|
|
|
Start the server with the CUTLASS quantized linear backend:
|
|
|
|
```bash
|
|
CUDA_VISIBLE_DEVICES=2,3 \
|
|
vllm serve feizhai123/qwen-image-2512-modelopt-mixed-fp8-sensitive-nvfp4-heavy \
|
|
--omni \
|
|
--host 0.0.0.0 \
|
|
--port 8091 \
|
|
--trust-remote-code \
|
|
--tensor-parallel-size 2 \
|
|
--linear-backend cutlass \
|
|
--force-cutlass-fp8
|
|
```
|
|
|
|
#### Verification
|
|
|
|
Run a direct image generation request after the server is ready:
|
|
|
|
```bash
|
|
curl http://localhost:8091/v1/images/generations \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"model": "feizhai123/qwen-image-2512-modelopt-mixed-fp8-sensitive-nvfp4-heavy",
|
|
"prompt": "A cinematic Warhammer 40,000 Ultramarine warrior in blue power armor, armor stained with alien ichor, swinging a chainsword at a Tyranid creature, gothic battlefield, dramatic lighting, high detail, no text, no watermark",
|
|
"negative_prompt": "blurry, low quality, text, watermark, logo, malformed armor, bad hands",
|
|
"size": "1024x1024",
|
|
"num_inference_steps": 20,
|
|
"true_cfg_scale": 4.0,
|
|
"guidance_scale": 4.0,
|
|
"seed": 48
|
|
}'
|
|
```
|
|
|
|
Check that:
|
|
|
|
- The server responds on `http://localhost:8091/health`.
|
|
- The response contains one generated image.
|
|
- Logs show CUTLASS selection for ModelOpt FP8 / mixed-precision linear
|
|
layers instead of falling back to the default automatic backend choice.
|
|
|
|
#### Benchmark
|
|
|
|
The numbers below are loaded-once request-level measurements, not an HTTP
|
|
concurrency benchmark. Each case loads the model once, runs warmup requests,
|
|
then measures 100 sequential requests.
|
|
|
|
```text
|
|
Hardware: 2x B200
|
|
Tensor parallel size: 2
|
|
Requests: 100
|
|
Concurrency: 1
|
|
Resolution: 1024x1024
|
|
Denoising steps: 20
|
|
```
|
|
|
|
| Config | Mean | P90 | P99 | Peak VRAM |
|
|
| --- | ---: | ---: | ---: | ---: |
|
|
| BF16 | 2.696s | 2.700s | 2.707s | 99,000 MiB |
|
|
| ModelOpt FP8 CUTLASS | 2.663s | 2.671s | 2.676s | 85,760 MiB |
|
|
| Mixed FP8/NVFP4 CUTLASS | 2.584s | 2.590s | 2.594s | 84,412 MiB |
|
|
|
|
The same 2-GPU setup was also used to sweep NVFP4 linear backends. Direct
|
|
CUTLASS was the fastest validated backend for this checkpoint.
|
|
|
|
| Backend | Mean | P90 | P99 | Peak VRAM |
|
|
| --- | ---: | ---: | ---: | ---: |
|
|
| auto | 2.927s | 2.948s | 3.535s | 85,340 MiB |
|
|
| flashinfer-cudnn | 3.523s | 3.528s | 3.766s | 84,500 MiB |
|
|
| flashinfer-trtllm | 2.711s | 2.727s | 3.010s | 84,996 MiB |
|
|
| flashinfer-cutlass | 2.935s | 2.950s | 3.011s | 85,340 MiB |
|
|
| cutlass | 2.578s | 2.584s | 2.592s | 84,412 MiB |
|
|
|
|
#### Notes
|
|
|
|
- Use `--linear-backend cutlass` to select the validated quantized linear
|
|
backend from the CLI.
|
|
- `--force-cutlass-fp8` keeps ModelOpt FP8 layers on the CUTLASS FP8 path.
|
|
- The benchmark table intentionally reports Qwen-Image-2512 as
|
|
concurrency-1 request-level data; do not compare it directly with an online
|
|
HTTP concurrency benchmark.
|