Qwen-Image-series 是通义千问团队推出的图像生成与编辑大模型系列,基于 DiT(Diffusion Transformer)架构,具备出色的文字渲染和多语言生成能力。
根据所需任务下载对应模型权重到本地 model/ 目录:
| 模型 | 功能 | HuggingFace | ModelScope |
|---|---|---|---|
| Qwen-Image | 文生图 | HuggingFace | ModelScope |
| Qwen-Image-2512 | 文生图(增强版) | HuggingFace | ModelScope |
| Qwen-Image-Edit-2511 | 图生图 | HuggingFace | ModelScope |
下载完成后,每个模型目录结构应包含:
model/Qwen-Image/
├── transformer/ # DiT 模型权重
├── text_encoder/ # 文本编码器
├── tokenizer/ # 分词器
├── scheduler/ # 调度器配置
└── vae/ # VAE 模型| 配套项 | 版本 |
|---|---|
| CANN | 8.5 |
| Python | 3.11.10 |
| PyTorch | 2.6.0 |
| torch_npu | 2.6.0 |
| torchvision | 0.21.0 |
| diffusers | 0.36.0 |
| transformers | 4.57.3 |
| yunchang | 0.6.0 |
从华为昇腾镜像仓库获取 MindIE 推理镜像(镜像已包含 CANN、MindIE、torch_npu):
yum install gcc gcc-c++ glibc-devel libstdc++-devel cmake make python3-devel libgccmindiesd 是华为昇腾提供的 Stable Diffusion 推理加速库,集成了算子优化、缓存加速、量化、并行等高阶特性。
源码地址:GitCode MindIE-SD
# 1. 检查并卸载旧版本
pip list | grep mindiesd
# 如果存在则卸载
pip uninstall mindiesd
# 2. 再次确认卸载干净
pip list | grep mindiesd
# 如果仍然存在,可能是被其他包依赖安装的,需要先卸载再重装
# 3. 编译安装 mindiesd
cd MindIE-SD
rm -rf dist
python setup.py bdist_wheel
cd dist
pip install mindiesd-*.whl源码地址:Modelers Qwen-Image-series
cd Qwen-Image-series
pip3 install -r requirements.txt依赖包含:
diffusers==0.36.0:HuggingFace 扩散模型框架transformers==4.57.3:文本编码器加载yunchang==0.6.0:分布式并行通信库使用 test-Qwen-Image-1.sh 脚本执行单卡推理:
bash test-Qwen-Image-1.sh脚本内容解析:
#!/bin/bash
set -e
# ====================== 全局环境变量配置 ======================
export PYTORCH_NPU_ALLOC_CONF='expandable_segments:True' # NPU显存动态分配
export ALGO=2 # 0:普通, 1:FA, 2:LA(高性能FA算子)
export OVERLAP=0 # 通信-计算重叠开关
export ROPE_FUSE=1 # RoPE算子融合
export ADALN_FUSE=1 # ADALN算子融合
export COND_CACHE=1 # 条件缓存
export UNCOND_CACHE=1 # 无条件缓存
export CACHE_STEP_START=10 # 缓存开始步骤
export CACHE_STEP_INTERVAL=3 # 缓存步骤间隔
export CACHE_STEP_END=35 # 缓存结束步骤
export CACHE_BLOCK_START=10 # 缓存开始块
export CACHE_BLOCK_END=50 # 缓存结束块
# ====================== 任务配置 ======================
TASK="Qwen-Image"
MODEL_PATH="../../model/Qwen-Image"
DEVICE_IDS="6" # 单卡设备ID
NPROC_PER_NODE=$(echo $DEVICE_IDS | tr ',' '\n' | wc -l)
MASTER_PORT=29508
# ====================== 设备配置 ======================
export ASCEND_RT_VISIBLE_DEVICES=${DEVICE_IDS}
TIME_STR=`date +"%Y%m%d%H%M%S"`
# ====================== 执行推理 ======================
torchrun --nproc_per_node=${NPROC_PER_NODE} --master-port ${MASTER_PORT} generate.py \
--task ${TASK} \
--ckpt_dir ${MODEL_PATH} \
--prompt '''A coffee shop entrance features a chalkboard sign reading "Qwen Coffee 😊 $2 per cup," with a neon light beside it displaying "通义千问". Next to it hangs a poster showing a beautiful Chinese woman, and beneath the poster is written "π≈3.1415926-53589793-23846264-33832795-02384197". Ultra HD, 4K, cinematic composition''' \
--negative_prompt " " \
--width 1024 \
--height 1024 \
--num_inference_steps 50 \
--seed 42 \
--output_file "./output/text_to_image-1-${TIME_STR}.png" \
--vae_tiling \
--vae_slicing \推理结果:50步推理端到端耗时约 25.57秒。
验证日志(Qwen-Image单卡日志(COND_CACHE).txt):
[Rank 0][2026-03-17 11:36:18][INFO] 开始初始化推理环境,Rank:0/0,本地Rank:0
[Rank 0][2026-03-17 11:36:18][INFO] 初始化NPU设备成功,设备ID:0
[Rank 0][2026-03-17 11:36:18][INFO] 模型数据类型:torch.bfloat16,运行设备:npu:0
Loading checkpoint shards: 100%|██████████| 9/9 [00:00<00:00, 23.83it/s]
[Rank 0][2026-03-17 11:36:19][INFO] 开始初始化Qwen-Image任务Pipeline
Loading pipeline components...: 100%|██████████| 5/5 [00:00<00:00, 5.90it/s]
[Rank 0][2026-03-17 11:36:23][INFO] 启用VAE分块推理(vae_tiling)
[Rank 0][2026-03-17 11:36:23][INFO] 启用VAE切片推理(vae_slicing)
[Rank 0][2026-03-17 11:36:23][INFO] 启用缓存配置,COND_CACHE=True, UNCOND_CACHE=True,配置:{'method': 'dit_block_cache', 'blocks_count': 60, 'steps_count': 50, 'step_start': 10, 'step_interval': 3, 'step_end': 35, 'block_start': 10, 'block_end': 50}
[Rank 0][2026-03-17 11:36:23][INFO] 开始模型预热(3步推理),解决首次算子编译耗时
100%|██████████| 3/3 [00:03<00:00, 1.32s/it]
100%|██████████| 50/50 [00:24<00:00, 2.05it/s]
[Rank 0][2026-03-17 11:36:56][INFO] 正式推理完成,端到端耗时:25.5781秒
[Rank 0][2026-03-17 11:36:56][INFO] 生成图片保存成功:/data01/xxx/Qwen-Image-series/output/text_to_image-1-20260317113557_0.png
[Rank 0][2026-03-17 11:36:56][INFO] 开始释放推理资源,清理显存/内存
[Rank 0][2026-03-17 11:37:00][INFO] 资源释放完成
[Rank 0][2026-03-17 11:37:00][INFO] Rank 0 推理任务全部完成使用 test-Qwen-Image-2.sh 脚本执行双卡推理:
bash test-Qwen-Image-2.sh脚本内容解析:
#!/bin/bash
set -e
# ====================== 全局环境变量配置 ======================
export PYTORCH_NPU_ALLOC_CONF='expandable_segments:True'
export ALGO=2 # 使用高性能FA算子(LA)
export OVERLAP=0 # 通信-计算重叠开关
export ROPE_FUSE=1 # RoPE算子融合
export ADALN_FUSE=1 # ADALN算子融合
export COND_CACHE=1 # 条件缓存
export UNCOND_CACHE=1 # 无条件缓存
export CACHE_STEP_START=10
export CACHE_STEP_INTERVAL=3
export CACHE_STEP_END=35
export CACHE_BLOCK_START=10
export CACHE_BLOCK_END=50
# ====================== 任务配置 ======================
TASK="Qwen-Image"
MODEL_PATH="../../model/Qwen-Image"
DEVICE_IDS="6,7" # 双卡设备ID
NPROC_PER_NODE=$(echo $DEVICE_IDS | tr ',' '\n' | wc -l)
MASTER_PORT=29508
# ====================== 设备配置 ======================
export ASCEND_RT_VISIBLE_DEVICES=${DEVICE_IDS}
TIME_STR=`date +"%Y%m%d%H%M%S"`
# ====================== 执行推理 ======================
# 2卡并行:cfg_size=2 ulysses_size=1(推荐配置)
torchrun --nproc_per_node=${NPROC_PER_NODE} --master-port ${MASTER_PORT} generate.py \
--task ${TASK} \
--ckpt_dir ${MODEL_PATH} \
--prompt '''A coffee shop entrance features a chalkboard sign reading "Qwen Coffee 😊 $2 per cup," with a neon light beside it displaying "通义千问". Next to it hangs a poster showing a beautiful Chinese woman, and beneath the poster is written "π≈3.1415926-53589793-23846264-33832795-02384197". Ultra HD, 4K, cinematic composition''' \
--negative_prompt " " \
--width 1024 \
--height 1024 \
--num_inference_steps 50 \
--seed 42 \
--output_file "./output/text_to_image-2-${TIME_STR}.png" \
--vae_tiling \
--vae_slicing \
--cfg_size 2 \
--ulysses_size 1推理结果:50步推理端到端耗时约 13.41秒,相比单卡加速约 1.91倍。
验证日志(Qwen-Image双卡日志(COND_CACHE).txt):
[Rank 0][2026-03-17 11:39:39][INFO] 开始初始化推理环境,Rank:0/1,本地Rank:0
[Rank 0][2026-03-17 11:39:39][INFO] 初始化NPU设备成功,设备ID:0
[Rank 0][2026-03-17 11:39:39][INFO] 分布式进程组初始化成功,后端:hccl
[Rank 0][2026-03-17 11:39:39][INFO] 并行环境初始化成功,配置:{'tp_degree': 1, 'sp_degree': 1, 'ulysses_degree': 1, 'ring_degree': 1, 'use_cfg_parallel': True, 'world_size': 2, 'cfg_degree': 2}
[Rank 0][2026-03-17 11:39:39][INFO] 模型数据类型:torch.bfloat16,运行设备:npu:0
Loading checkpoint shards: 100%|██████████| 9/9 [00:00<00:00, 24.08it/s]
[Rank 0][2026-03-17 11:39:40][INFO] 开始初始化Qwen-Image任务Pipeline
Loading pipeline components...: 100%|██████████| 5/5 [00:00<00:00, 5.94it/s]
[Rank 0][2026-03-17 11:39:44][INFO] 启用VAE分块推理(vae_tiling)
[Rank 0][2026-03-17 11:39:44][INFO] 启用VAE切片推理(vae_slicing)
[Rank 0][2026-03-17 11:39:44][INFO] 启用缓存配置,COND_CACHE=True, UNCOND_CACHE=True,配置:{'method': 'dit_block_cache', 'blocks_count': 60, 'steps_count': 50, 'step_start': 10, 'step_interval': 3, 'step_end': 35, 'block_start': 10, 'block_end': 50}
[Rank 0][2026-03-17 11:39:44][INFO] 开始模型预热(3步推理),解决首次算子编译耗时
100%|██████████| 3/3 [00:03<00:00, 1.24s/it]
100%|██████████| 50/50 [00:12<00:00, 4.09it/s]
[Rank 0][2026-03-17 11:40:05][INFO] 正式推理完成,端到端耗时:13.4181秒
[Rank 0][2026-03-17 11:40:06][INFO] 生成图片保存成功:/data01/xxx/Qwen-Image-series/output/text_to_image-2-20260317113918_0.png
[Rank 0][2026-03-17 11:40:06][INFO] 开始释放推理资源,清理显存/内存
[Rank 0][2026-03-17 11:40:10][INFO] 资源释放完成
[Rank 0][2026-03-17 11:40:10][INFO] 分布式进程组销毁成功
[Rank 0][2026-03-17 11:40:10][INFO] Rank 0 推理任务全部完成使用 test-Qwen-Image-2512-1.sh 脚本执行单卡推理:
bash test-Qwen-Image-2512-1.sh脚本内容解析:
#!/bin/bash
set -e
# ====================== 全局环境变量配置 ======================
export PYTORCH_NPU_ALLOC_CONF='expandable_segments:True'
export ALGO=2 # 0:普通, 1:FA, 2:LA
export OVERLAP=0 # 通信-计算重叠开关
export ROPE_FUSE=1 # RoPE算子融合
export ADALN_FUSE=1 # ADALN算子融合
export COND_CACHE=1 # 条件缓存
export UNCOND_CACHE=1 # 无条件缓存
export CACHE_STEP_START=10
export CACHE_STEP_INTERVAL=3
export CACHE_STEP_END=35
export CACHE_BLOCK_START=10
export CACHE_BLOCK_END=50
# ====================== 任务配置 ======================
TASK="Qwen-Image-2512"
MODEL_PATH="../../model/Qwen-Image-2512"
DEVICE_IDS="6"
NPROC_PER_NODE=$(echo $DEVICE_IDS | tr ',' '\n' | wc -l)
MASTER_PORT=29508
# ====================== 设备配置 ======================
export ASCEND_RT_VISIBLE_DEVICES=${DEVICE_IDS}
TIME_STR=`date +"%Y%m%d%H%M%S"`
# ====================== 执行推理 ======================
torchrun --nproc_per_node=${NPROC_PER_NODE} --master-port ${MASTER_PORT} generate.py \
--task ${TASK} \
--ckpt_dir ${MODEL_PATH} \
--prompt '''A coffee shop entrance features a chalkboard sign reading "Qwen Coffee 😊 $2 per cup," with a neon light beside it displaying "通义千问". Next to it hangs a poster showing a beautiful Chinese woman, and beneath the poster is written "π≈3.1415926-53589793-23846264-33832795-02384197". Ultra HD, 4K, cinematic composition''' \
--negative_prompt " " \
--width 1024 \
--height 1024 \
--num_inference_steps 50 \
--seed 42 \
--output_file "./output/text_to_image_2512-1-${TIME_STR}.png" \
--vae_tiling \
--vae_slicing \推理结果:50步推理端到端耗时约 25.58秒。
验证日志(Qwen-Image-2512单卡日志(COND_CACHE).txt):
[Rank 0][2026-03-14 13:24:56][INFO] 开始初始化推理环境,Rank:0/0,本地Rank:0
[Rank 0][2026-03-14 13:24:56][INFO] 初始化NPU设备成功,设备ID:0
[Rank 0][2026-03-14 13:24:56][INFO] 模型数据类型:torch.bfloat16,运行设备:npu:0
Loading checkpoint shards: 100%|██████████| 9/9 [00:00<00:00, 23.52it/s]
[Rank 0][2026-03-14 13:24:56][INFO] 开始初始化Qwen-Image-2512任务Pipeline
Loading pipeline components...: 100%|██████████| 5/5 [00:00<00:00, 5.89it/s]
[Rank 0][2026-03-14 13:25:01][INFO] 启用VAE分块推理(vae_tiling)
[Rank 0][2026-03-14 13:25:01][INFO] 启用VAE切片推理(vae_slicing)
[Rank 0][2026-03-14 13:25:01][INFO] 启用缓存配置,COND_CACHE=True, UNCOND_CACHE=True,配置:{'method': 'dit_block_cache', 'blocks_count': 60, 'steps_count': 50, 'step_start': 10, 'step_interval': 3, 'step_end': 35, 'block_start': 10, 'block_end': 50}
[Rank 0][2026-03-14 13:25:01][INFO] 开始模型预热(3步推理),解决首次算子编译耗时
[Rank 0][2026-03-14 13:25:34][INFO] 正式推理完成,端到端耗时:25.5883秒
[Rank 0][2026-03-14 13:25:34][INFO] 生成图片保存成功:/data01/xxx/Qwen-Image-series/output/text_to_image_2512-1-20260314132435_0.png
[Rank 0][2026-03-14 13:25:34][INFO] 开始释放推理资源,清理显存/内存
[Rank 0][2026-03-14 13:25:38][INFO] 资源释放完成
[Rank 0][2026-03-14 13:25:38][INFO] Rank 0 推理任务全部完成使用 test-Qwen-Image-2512-2.sh 脚本执行双卡推理:
bash test-Qwen-Image-2512-2.sh脚本内容解析:
#!/bin/bash
set -e
# ====================== 全局环境变量配置 ======================
export PYTORCH_NPU_ALLOC_CONF='expandable_segments:True'
export ALGO=2 # 0:普通, 1:FA, 2:LA
export OVERLAP=0 # 通信-计算重叠开关
export ROPE_FUSE=1 # RoPE算子融合
export ADALN_FUSE=1 # ADALN算子融合
export COND_CACHE=1 # 条件缓存
export UNCOND_CACHE=1 # 无条件缓存
export CACHE_STEP_START=10
export CACHE_STEP_INTERVAL=3
export CACHE_STEP_END=35
export CACHE_BLOCK_START=10
export CACHE_BLOCK_END=50
# ====================== 任务配置 ======================
TASK="Qwen-Image-2512"
MODEL_PATH="../../model/Qwen-Image-2512"
DEVICE_IDS="6,7"
NPROC_PER_NODE=$(echo $DEVICE_IDS | tr ',' '\n' | wc -l)
MASTER_PORT=29508
# ====================== 设备配置 ======================
export ASCEND_RT_VISIBLE_DEVICES=${DEVICE_IDS}
TIME_STR=`date +"%Y%m%d%H%M%S"`
# ====================== 执行推理 ======================
# 2卡并行:cfg_size=2 ulysses_size=1(推荐配置)
torchrun --nproc_per_node=${NPROC_PER_NODE} --master-port ${MASTER_PORT} generate.py \
--task ${TASK} \
--ckpt_dir ${MODEL_PATH} \
--prompt '''A coffee shop entrance features a chalkboard sign reading "Qwen Coffee 😊 $2 per cup," with a neon light beside it displaying "通义千问". Next to it hangs a poster showing a beautiful Chinese woman, and beneath the poster is written "π≈3.1415926-53589793-23846264-33832795-02384197". Ultra HD, 4K, cinematic composition''' \
--negative_prompt " " \
--width 1024 \
--height 1024 \
--num_inference_steps 50 \
--seed 42 \
--output_file "./output/text_to_image_2512-2-${TIME_STR}.png" \
--vae_tiling \
--vae_slicing \
--cfg_size 2 \
--ulysses_size 1推理结果:50步推理端到端耗时约 13.35秒,相比单卡加速约 1.92倍。
验证日志(Qwen-Image-2512双卡日志(COND_CACHE).txt):
[Rank 0][2026-03-14 17:36:31][INFO] 开始初始化推理环境,Rank:0/1,本地Rank:0
[Rank 0][2026-03-14 17:36:31][INFO] 初始化NPU设备成功,设备ID:0
[Rank 0][2026-03-14 17:36:31][INFO] 分布式进程组初始化成功,后端:hccl
[Rank 0][2026-03-14 17:36:31][INFO] 并行环境初始化成功,配置:{'tp_degree': 1, 'sp_degree': 1, 'ulysses_degree': 1, 'ring_degree': 1, 'use_cfg_parallel': True, 'world_size': 2, 'cfg_degree': 2}
[Rank 0][2026-03-14 17:36:31][INFO] 模型数据类型:torch.bfloat16,运行设备:npu:0
Loading checkpoint shards: 100%|██████████| 9/9 [00:00<00:00, 23.56it/s]
[Rank 0][2026-03-14 17:36:32][INFO] 开始初始化Qwen-Image-2512任务Pipeline
Loading pipeline components...: 100%|██████████| 5/5 [00:00<00:00, 5.90it/s]
[Rank 0][2026-03-14 17:36:36][INFO] 启用VAE分块推理(vae_tiling)
[Rank 0][2026-03-14 17:36:36][INFO] 启用VAE切片推理(vae_slicing)
[Rank 0][2026-03-14 17:36:36][INFO] 启用缓存配置,COND_CACHE=True, UNCOND_CACHE=True,配置:{'method': 'dit_block_cache', 'blocks_count': 60, 'steps_count': 50, 'step_start': 10, 'step_interval': 3, 'step_end': 35, 'block_start': 10, 'block_end': 50}
[Rank 0][2026-03-14 17:36:36][INFO] 开始模型预热(3步推理),解决首次算子编译耗时
[Rank 0][2026-03-14 17:36:57][INFO] 正式推理完成,端到端耗时:13.3536秒
[Rank 0][2026-03-14 17:36:58][INFO] 生成图片保存成功:/data01/xxx/Qwen-Image-series/output/text_to_image_2512-2-20260314173610_0.png
[Rank 0][2026-03-14 17:36:58][INFO] 开始释放推理资源,清理显存/内存
[Rank 0][2026-03-14 17:37:01][INFO] 资源释放完成
[Rank 0][2026-03-14 17:37:01][INFO] 分布式进程组销毁成功
[Rank 0][2026-03-14 17:37:01][INFO] Rank 0 推理任务全部完成使用 test-Qwen-Image-Edit-2511-1.sh 脚本执行单卡推理:
bash test-Qwen-Image-Edit-2511-1.sh脚本内容解析:
#!/bin/bash
set -e
# ====================== 全局环境变量配置 ======================
export PYTORCH_NPU_ALLOC_CONF='expandable_segments:True'
export ALGO=2 # 0:普通, 1:FA, 2:LA
export OVERLAP=0 # 通信-计算重叠开关
export ROPE_FUSE=1 # RoPE算子融合
export ADALN_FUSE=1 # ADALN算子融合
export COND_CACHE=1 # 条件缓存
export UNCOND_CACHE=1 # 无条件缓存
export CACHE_STEP_START=10
export CACHE_STEP_INTERVAL=3
export CACHE_STEP_END=35
export CACHE_BLOCK_START=10
export CACHE_BLOCK_END=50
# ====================== 任务配置 ======================
TASK="Qwen-Image-Edit-2511"
MODEL_PATH="../../model/Qwen-Image-Edit-2511"
DEVICE_IDS="6"
NPROC_PER_NODE=$(echo $DEVICE_IDS | tr ',' '\n' | wc -l)
MASTER_PORT=29508
# ====================== 设备配置 ======================
export ASCEND_RT_VISIBLE_DEVICES=${DEVICE_IDS}
TIME_STR=`date +"%Y%m%d%H%M%S"`
# ====================== 执行推理 ======================
torchrun --nproc_per_node=${NPROC_PER_NODE} --master-port ${MASTER_PORT} generate.py \
--task ${TASK} \
--ckpt_dir ${MODEL_PATH} \
--image "./examples/yarn-art-pikachu.png" \
--prompt "Make Pikachu hold a sign that says 'Qwen Edit is awesome', yarn art style, detailed, vibrant color" \
--negative_prompt " " \
--width 1024 \
--height 1024 \
--num_inference_steps 40 \
--seed 42 \
--output_file "./output/image_edit_2511-1-${TIME_STR}.png" \
--vae_tiling \
--vae_slicing \推理结果:40步推理端到端耗时约 50.64秒。
验证日志(Qwen-Image-Edit-2511单卡日志(COND_CACHE).txt):
[Rank 0][2026-03-14 13:10:20][INFO] 开始初始化推理环境,Rank:0/0,本地Rank:0
[Rank 0][2026-03-14 13:10:20][INFO] 初始化NPU设备成功,设备ID:0
[Rank 0][2026-03-14 13:10:20][INFO] 模型数据类型:torch.bfloat16,运行设备:npu:0
Loading checkpoint shards: 100%|██████████| 5/5 [00:02<00:00, 2.47it/s]
[Rank 0][2026-03-14 13:10:23][INFO] 开始初始化Qwen-Image-Edit-2511任务Pipeline
Loading pipeline components...: 100%|██████████| 6/6 [00:02<00:00, 2.13it/s]
[Rank 0][2026-03-14 13:10:54][INFO] 启用VAE分块推理(vae_tiling)
[Rank 0][2026-03-14 13:10:54][INFO] 启用VAE切片推理(vae_slicing)
[Rank 0][2026-03-14 13:10:54][INFO] 启用缓存配置,COND_CACHE=True, UNCOND_CACHE=True,配置:{'method': 'dit_block_cache', 'blocks_count': 60, 'steps_count': 40, 'step_start': 10, 'step_interval': 3, 'step_end': 35, 'block_start': 10, 'block_end': 50}
[Rank 0][2026-03-14 13:10:54][INFO] 成功加载图片[1/1]:./examples/yarn-art-pikachu.png
[Rank 0][2026-03-14 13:10:54][INFO] 开始模型预热(3步推理),解决首次算子编译耗时
[Rank 0][2026-03-14 13:11:57][INFO] 正式推理完成,端到端耗时:50.6452秒
[Rank 0][2026-03-14 13:11:58][INFO] 生成图片保存成功:/data01/xxx/Qwen-Image-series/output/image_edit_2511-1-20260314131000_0.png
[Rank 0][2026-03-14 13:11:58][INFO] 开始释放推理资源,清理显存/内存
[Rank 0][2026-03-14 13:12:02][INFO] 资源释放完成
[Rank 0][2026-03-14 13:12:02][INFO] Rank 0 推理任务全部完成使用 test-Qwen-Image-Edit-2511-2.sh 脚本执行双卡推理:
bash test-Qwen-Image-Edit-2511-2.sh脚本内容解析:
#!/bin/bash
set -e
# ====================== 全局环境变量配置 ======================
export PYTORCH_NPU_ALLOC_CONF='expandable_segments:True'
export ALGO=2 # 0:普通, 1:FA, 2:LA
export OVERLAP=0 # 通信-计算重叠开关
export ROPE_FUSE=1 # RoPE算子融合
export ADALN_FUSE=1 # ADALN算子融合
export COND_CACHE=1 # 条件缓存
export UNCOND_CACHE=1 # 无条件缓存
export CACHE_STEP_START=10
export CACHE_STEP_INTERVAL=3
export CACHE_STEP_END=35
export CACHE_BLOCK_START=10
export CACHE_BLOCK_END=50
# ====================== 任务配置 ======================
TASK="Qwen-Image-Edit-2511"
MODEL_PATH="../../model/Qwen-Image-Edit-2511"
DEVICE_IDS="6,7"
NPROC_PER_NODE=$(echo $DEVICE_IDS | tr ',' '\n' | wc -l)
MASTER_PORT=29508
# ====================== 设备配置 ======================
export ASCEND_RT_VISIBLE_DEVICES=${DEVICE_IDS}
TIME_STR=`date +"%Y%m%d%H%M%S"`
# ====================== 执行推理 ======================
# 2卡并行:cfg_size=2 ulysses_size=1(推荐配置)
torchrun --nproc_per_node=${NPROC_PER_NODE} --master-port ${MASTER_PORT} generate.py \
--task ${TASK} \
--ckpt_dir ${MODEL_PATH} \
--image "./examples/yarn-art-pikachu.png" \
--prompt "Make Pikachu hold a sign that says 'Qwen Edit is awesome', yarn art style, detailed, vibrant color" \
--negative_prompt " " \
--width 1024 \
--height 1024 \
--num_inference_steps 40 \
--seed 42 \
--output_file "./output/image_edit_2511-2-${TIME_STR}.png" \
--vae_tiling \
--vae_slicing \
--cfg_size 2 \
--ulysses_size 1推理结果:40步推理端到端耗时约 26.23秒,相比单卡加速约 1.93倍。
验证日志(Qwen-Image-Edit-2511双卡日志(COND_CACHE).txt):
[Rank 0][2026-03-14 13:19:19][INFO] 开始初始化推理环境,Rank:0/1,本地Rank:0
[Rank 0][2026-03-14 13:19:19][INFO] 初始化NPU设备成功,设备ID:0
[Rank 0][2026-03-14 13:19:19][INFO] 分布式进程组初始化成功,后端:hccl
[Rank 0][2026-03-14 13:19:19][INFO] 并行环境初始化成功,配置:{'tp_degree': 1, 'sp_degree': 1, 'ulysses_degree': 1, 'ring_degree': 1, 'use_cfg_parallel': True, 'world_size': 2, 'cfg_degree': 2}
[Rank 0][2026-03-14 13:19:19][INFO] 模型数据类型:torch.bfloat16,运行设备:npu:0
Loading checkpoint shards: 100%|██████████| 5/5 [00:00<00:00, 16.20it/s]
[Rank 0][2026-03-14 13:19:19][INFO] 开始初始化Qwen-Image-Edit-2511任务Pipeline
Loading pipeline components...: 100%|██████████| 6/6 [00:02<00:00, 2.92it/s]
[Rank 0][2026-03-14 13:19:26][INFO] 启用VAE分块推理(vae_tiling)
[Rank 0][2026-03-14 13:19:26][INFO] 启用VAE切片推理(vae_slicing)
[Rank 0][2026-03-14 13:19:26][INFO] 启用缓存配置,COND_CACHE=True, UNCOND_CACHE=True,配置:{'method': 'dit_block_cache', 'blocks_count': 60, 'steps_count': 40, 'step_start': 10, 'step_interval': 3, 'step_end': 35, 'block_start': 10, 'block_end': 50}
[Rank 0][2026-03-14 13:19:26][INFO] 成功加载图片[1/1]:./examples/yarn-art-pikachu.png
[Rank 0][2026-03-14 13:19:26][INFO] 开始模型预热(3步推理),解决首次算子编译耗时
[Rank 0][2026-03-14 13:20:02][INFO] 正式推理完成,端到端耗时:26.2365秒
[Rank 0][2026-03-14 13:20:02][INFO] 生成图片保存成功:/data01/xxx/Qwen-Image-series/output/image_edit_2511-2-20260314131858_0.png
[Rank 0][2026-03-14 13:20:06][INFO] 开始释放推理资源,清理显存/内存
[Rank 0][2026-03-14 13:20:06][INFO] 资源释放完成
[Rank 0][2026-03-14 13:20:06][INFO] 分布式进程组销毁成功
[Rank 0][2026-03-14 13:20:06][INFO] Rank 0 推理任务全部完成本推理方案从算子级优化、算法级优化、显存优化、并行加速和推理流程优化五个维度进行了全面优化,充分发挥昇腾 NPU 硬件性能。
| 优化项 | 环境变量 | 说明 |
|---|---|---|
| 高性能 Attention 算子(LA) | ALGO=2 | 替换默认 SDPA 算子为昇腾自研 Laser Attention(LA)算子。ALGO=0 为默认 SDPA,ALGO=1 为 FA 算子,ALGO=2 为高性能 FA 算子(推荐) |
| RoPE 算子融合 | ROPE_FUSE=1 | 将 Rotary Position Embedding 的多个小算子融合为一个大算子,减少 kernel launch 开销 |
| ADALN 算子融合 | ADALN_FUSE=1 | 将 Adaptive Layer Normalization 相关算子融合,减少显存访问次数 |
| 优化项 | 环境变量 | 说明 |
|---|---|---|
| 条件输入缓存(COND_CACHE) | COND_CACHE=1 | 在扩散去噪过程中,条件分支的 DiT Block 输出在特定步骤间变化较小,可缓存复用,跳过冗余计算 |
| 无条件输入缓存(UNCOND_CACHE) | UNCOND_CACHE=1 | 同理,无条件分支的 DiT Block 输出也可缓存复用 |
缓存参数精细控制:
| 参数 | 默认值 | 说明 |
|---|---|---|
CACHE_STEP_START | 10 | 缓存开始的去噪步骤(前几步变化剧烈,不宜缓存) |
CACHE_STEP_INTERVAL | 3 | 缓存间隔步数(每隔几步复用一次缓存) |
CACHE_STEP_END | 35 | 缓存结束的去噪步骤(后续步骤需精确计算) |
CACHE_BLOCK_START | 10 | 缓存起始 Block 编号 |
CACHE_BLOCK_END | 50 | 缓存结束 Block 编号 |
CACHE_BLOCKS_COUNT | 60 | DiT 总 Block 数量 |
原理:扩散模型在去噪过程中,中间步骤的 DiT Block 输出变化较小(尤其是无条件分支),通过
dit_block_cache方法在指定步骤范围内对特定 Block 的输出进行缓存和复用,避免重复计算,从而实现约 1.3~1.6 倍的加速。
| 优化项 | 启动参数 | 说明 |
|---|---|---|
| VAE Tiling | --vae_tiling | 将 VAE 解码过程分块处理,每次只处理图像的一个 tile,大幅降低 VAE 解码的峰值显存占用 |
| VAE Slicing | --vae_slicing | 将 VAE 解码的 batch 维度切片处理,逐 batch 推理,降低显存峰值 |
| 低 CPU 内存加载 | low_cpu_mem_usage=True | 模型加载时使用低内存模式,避免加载过程中 CPU 内存溢出 |
| NPU 显存动态分配 | PYTORCH_NPU_ALLOC_CONF='expandable_segments:True' | 启用 NPU 显存段的动态扩展,减少显存碎片,提高显存利用率 |
| 模型量化 | --quant_dit_path | 支持 w8a8(8bit权重+8bit激活)和 w8a16(8bit权重+16bit激活)量化,降低 DiT 模型显存占用 |
| 优化项 | 启动参数 | 说明 |
|---|---|---|
| CFG 并行 | --cfg_size 2 | Classifier-Free Guidance 的条件/无条件分支分别在两张卡上并行计算,避免串行执行,是最有效的双卡并行策略 |
| Ulysses 序列并行 | --ulysses_size N | 将 Transformer 的序列维度切分到多张卡上并行计算,ulysses_size 需为 24 的因数 |
| 通信-计算重叠 | OVERLAP=1 | 在开启 Ulysses 并行时,将通信操作与计算操作重叠执行,隐藏通信延迟(仅在 Ulysses + 多卡环境下生效) |
并行策略推荐(卡数与并行度对应关系):
| 卡数 | 推荐 cfg_size | 推荐 ulysses_size | 说明 |
|---|---|---|---|
| 1 | 1 | 1 | 单卡无并行 |
| 2 | 2 | 1 | CFG 并行优于 Ulysses |
| 4 | 2 | 2 | CFG + Ulysses 组合 |
| 8 | 2 | 4 | CFG + Ulysses 组合 |
| 16 | 2 | 8 | CFG + Ulysses 组合 |
约束:
cfg_size × ulysses_size必须等于分布式进程数(即使用的 NPU 卡数),且cfg_size只能取值 1 或 2。
| 优化项 | 实现方式 | 说明 |
|---|---|---|
| 模型预热 | 先运行 3 步推理 | 首次推理会触发算子编译(JIT),预热 3 步后再进行正式推理,排除编译耗时 |
| 分布式屏障同步 | dist.barrier() | 预热完成后等待所有进程同步,确保正式推理前各进程状态一致 |
| 设备同步计时 | torch.npu.synchronize() | 在计时前后进行设备同步,确保耗时统计准确 |
| 资源及时释放 | 显式 del + gc + empty_cache | 推理完成后显式释放模型、pipeline,执行垃圾回收和 NPU 显存清空,避免显存泄漏和碎片 |
以下为 1024×1024 分辨率、开启全部优化(等价优化 + 缓存加速)的端到端推理耗时:
| 模型 | 推理步数 | 单卡耗时 | 双卡耗时 | 双卡加速比 |
|---|---|---|---|---|
| Qwen-Image | 50步 | ~25.57秒 | ~13.41秒 | ~1.91x |
| Qwen-Image-2512 | 50步 | ~25.58秒 | ~13.35秒 | ~1.92x |
| Qwen-Image-Edit-2511 | 40步 | ~50.64秒 | ~26.23秒 | ~1.93x |
| 参数 | 可选值 | 默认值 | 说明 |
|---|---|---|---|
ALGO | 0/1/2 | 0 | Attention 算子选择:0=SDPA,1=FA,2=LA(推荐) |
OVERLAP | 0/1 | 0 | 通信-计算重叠开关,需配合 Ulysses 并行使用 |
ROPE_FUSE | 0/1 | 0 | RoPE 算子融合开关 |
ADALN_FUSE | 0/1 | 0 | ADALN 算子融合开关 |
COND_CACHE | 0/1 | 0 | 条件输入缓存开关 |
UNCOND_CACHE | 0/1 | 0 | 无条件输入缓存开关 |
CACHE_STEP_START | 整数 | 10 | 缓存开始步骤 |
CACHE_STEP_INTERVAL | 整数 | 3 | 缓存步骤间隔 |
CACHE_STEP_END | 整数 | 35 | 缓存结束步骤 |
CACHE_BLOCK_START | 整数 | 10 | 缓存开始块 |
CACHE_BLOCK_END | 整数 | 50 | 缓存结束块 |
PYTORCH_NPU_ALLOC_CONF | - | - | NPU 显存分配策略 |
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
--task | str | Qwen-Image | 推理任务类型 |
--ckpt_dir | str | Qwen/Qwen-Image | 模型权重路径 |
--prompt | str | 示例提示词 | 正面提示词 |
--negative_prompt | str | " " | 负面提示词 |
--width | int | 1024 | 生成图片宽度 |
--height | int | 1024 | 生成图片高度 |
--num_inference_steps | int | 50 | 去噪步数 |
--seed | int | 42 | 随机种子 |
--output_file | str | text_to_image.png | 输出图片路径 |
--vae_tiling | flag | False | 启用 VAE 分块推理 |
--vae_slicing | flag | False | 启用 VAE 切片推理 |
--cfg_size | int | 1 | CFG 并行度(1或2) |
--ulysses_size | int | 1 | Ulysses 并行度 |
--cfg_scale | float | 4.0 | True CFG 缩放系数 |
--guidance_scale | float | 1.0 | 引导系数 |
--quant_dit_path | str | None | 量化模型路径(启用则加载量化权重) |
--lora_path | str | None | LoRA 权重路径 |
--torch_dtype | str | bfloat16 | 数据类型 |
Q1:显存不足怎么办?
开启 --vae_tiling --vae_slicing 降低 VAE 显存占用;降低 --width / --height 分辨率;使用量化模型(--quant_dit_path)。
Q2:多卡通信失败怎么办?
检查 ASCEND_RT_VISIBLE_DEVICES 是否正确设置,检查 --master-port 端口是否被占用,确保 cfg_size × ulysses_size 等于使用的卡数。
Q3:推理结果不一致怎么办?
固定 --seed 参数;注意缓存优化(COND_CACHE/UNCOND_CACHE)可能轻微影响生成质量,可按需调整缓存参数或关闭缓存。
Q4:如何调整模型权重路径?
修改脚本中的 MODEL_PATH 变量,指向模型权重的实际本地路径。