Our recently released LightX2V APP is a native macOS app for Apple Silicon Macs running macOS 14 or later. It uses LightX2V to run Qwen-Image-2.1-Turbo locally, with a graphical interface for text-to-image generation and image editing.
LightX2V APP also offers optional prompt enhancement with the accompanying Qwen-Image-2.1-PE-T2I-GGUF-Q8_0 and Qwen-Image-2.1-PE-I2I-GGUF-Q8_0 models.
Download the official weights from Qwen/Qwen-Image-2.1:
hf download Qwen/Qwen-Image-2.1 --local-dir Qwen/Qwen-Image-2.1Download the Turbo weights from Qwen/Qwen-Image-2.1-Turbo:
hf download Qwen/Qwen-Image-2.1-Turbo --local-dir Qwen/Qwen-Image-2.1-TurboChoose the LightX2V Docker image for your GPU. Pull the corresponding image in a working directory on the host:
# H100, A100, etc.
docker pull lightx2v/lightx2v:26062001
# RTX 5090
docker pull lightx2v/lightx2v:26062001-cu130-5090-fix-260921Start a container using the selected image:
docker run --gpus all -itd --ipc=host --name [container_name] -v [mount_settings] --entrypoint /bin/bash [image_id]Clone the LightX2V source inside the container:
git clone https://github.com/ModelTC/LightX2V.gitRun the following commands from the LightX2V repository root inside the container.
Set lightx2v_path (repository path), model_path (model root directory), and CUDA_VISIBLE_DEVICES (GPU ID) in the corresponding bash script.
# Text-to-image
bash scripts/qwen_image_21/qwen_image_21_t2i.sh
# Image-to-image
bash scripts/qwen_image_21/qwen_image_21_i2i.shEdit --prompt, --image_path, --size, --seed, and --save_result_path directly in the script as needed.
Use --size HEIGHT WIDTH. Both dimensions must be at least 32; non-multiples of 32 are rounded down automatically.
For image-to-image, remove the script's --size argument to determine the output size from the reference image's aspect ratio. The pixel count is approximately resolution² (resolution defaults to 1024 in the config), with each dimension rounded to the nearest multiple of 32.
Pass --resolution 2048 to override the config for one request; omit it to use the config. The value must be a positive integer. It controls reference-image resizing and automatic output sizing; an explicit --size still determines the output dimensions.
The default config already enables the general optimization path: FlashAttention3, FlashInfer RoPE, Triton LayerNorm and modulation, fused QK RMSNorm, fused transformer-block operators, CFG-disabled inference, and OpenCV result saving.
Qwen-Image-2.1-Turbo is the official accelerated version of Qwen-Image-2.1. It supports text-to-image generation and image editing with 8 denoising steps.
Set lightx2v_path, model_path (the Qwen-Image-2.1-Turbo directory), and CUDA_VISIBLE_DEVICES in the scripts, then run:
# Text-to-image
bash scripts/qwen_image_21/qwen_image_21_turbo_t2i.sh
# Image-to-image
bash scripts/qwen_image_21/qwen_image_21_turbo_i2i.shFor image-to-image, edit --image_path and --prompt as needed. The default input is the model's assets/turbo-boat-input.png.
The examples use these optimization techniques:
- FP8 DiT linears with FP16 accumulation and FP8 QwenVL language weights.
- SageAttention2 and FlashInfer RoPE.
- Triton LayerNorm/modulation, fused QK RMSNorm and transformer-block operators.
- Text encoder offload and VAE torch.compile.
- Ulysses SP, FP8 communication, grouped head parallelism, language TP and VAE parallelism.
Convert the DiT weights:
python tools/convert/converter.py \
--source /path/to/Qwen-Image-2.1/transformer \
--output /path/to/Qwen-Image-2.1-fp8-f16-accum \
--output_name qwen_image_21_fp8_f16_accum \
--model_type qwen_image_21_dit \
--quantization_profile qwen-image-21-fp8-f16-accum \
--quantized --linear_type fp8 --device cuda:0 --single_fileFor QwenVL FP8 conversion, see the example in convert_qwen_image_21_text_encoder_fp8 in converter.py. Set dit_quantized_ckpt and text_encoder_quantized_ckpt in the corresponding JSON, and set the repository path, original model path and GPU IDs in the scripts.
# Single GPU, 1K: text-to-image / image-to-image
bash scripts/qwen_image_21/qwen_image_21_t2i_5090_1k.sh
bash scripts/qwen_image_21/qwen_image_21_i2i_5090_1k.sh
# Single GPU, 2K: text-to-image / image-to-image
bash scripts/qwen_image_21/qwen_image_21_t2i_5090_2k.sh
bash scripts/qwen_image_21/qwen_image_21_i2i_5090_2k.sh
# Dual GPU, 2K: text-to-image / image-to-image
bash scripts/qwen_image_21/qwen_image_21_t2i_5090_2k_sp2.sh
bash scripts/qwen_image_21/qwen_image_21_i2i_5090_2k_sp2.sh| GPU | Task | Output resolution | End-to-end latency |
|---|---|---|---|
| RTX 5090 ×1 | T2I | 1024×1024 | 5.586 s |
| RTX 5090 ×1 | I2I | 1024×1024 | 6.804 s |
| RTX 5090 ×1 | T2I | 2048×2048 | 30.333 s |
| RTX 5090 ×1 | I2I | 2048×2048 | 42.787 s |
| RTX 5090 ×2 | T2I | 2048×2048 | 16.868 s |
| RTX 5090 ×2 | I2I | 2048×2048 | 25.212 s |
Tests use PyTorch 2.11.0+cu130, 40 steps, seed 42, CFG disabled, and the example prompts. I2I uses assets/inputs/imgs/girl.png, preprocessed at the corresponding resolution.
Latency is the median of three consecutive requests after the first request in the same instance; dual-GPU samples use the slower rank. End-to-end timing includes image saving and excludes model loading and one-time initialization.
Search the runtime log for RUN pipeline cost to find the pipeline latency in seconds.
Set the repository path, model path, and GPU ID in server/start_server.sh, then start the server:
bash scripts/qwen_image_21/server/start_server.shThe default port is 8000. The server supports both text-to-image and image-to-image requests.
Once the server is ready, open a new terminal in the same container and send requests:
# Text-to-image
python scripts/qwen_image_21/server/post_t2i.py
# Image-to-image
python scripts/qwen_image_21/server/post_i2i.pyEdit url, message, and output_path directly; for image-to-image, also set image_path. The scripts already specify task: "t2i" and task: "i2i", respectively.
Service requests follow the same size rules. For automatic image-to-image sizing, remove size from message.
Set "resolution": 2048 in message to override the startup config for that request; omit it or use null to keep the config. The image form endpoint and /v1/images/generations and /v1/images/edits also accept resolution.