m0_63918125/dreamshaper-7
模型介绍
文件和版本
Pull Requests
讨论
分析

Lykon/dreamshaper-7 on Ascend NPU (torch_npu 2.9.0.post1)

1. 简介

本文档记录 Lykon/dreamshaper-7(Stable Diffusion 1.5 微调的文生图模型)在华为昇腾 NPU(Ascend910)上,基于 diffusers + torch_npu 的真实推理适配与验证结果。

  • 模型结构:Stable Diffusion 1.5 微调,StableDiffusionPipeline 组成为 UNet2DConditionModel(cross_attention_dim=768,参数 859,520,964)+ AutoencoderKL VAE(83,653,863)+ CLIPTextModel 文本编码器(123,060,480)+ DEISMultistepScheduler。
  • dtype:float32(为正确性对照强制全精度,7.7 GB fp32 权重在 65 GB HBM 下峰值仅约 8.6 GB,绰绰有余),任务类型:text-to-image。
  • 生成配置:num_inference_steps=25、guidance_scale=7.5(标准 SD1.5 多步 + CFG 用法)。

适配要点:

  • 无需 trust_remote_code、无自定义算子;StableDiffusionPipeline.from_pretrained(dir, torch_dtype=torch.float32, safety_checker=None, requires_safety_checker=False) 后 pipe.to("npu:0") 即可整条管线上 NPU 真跑。
  • 显式关闭 safety_checker(safety_checker=None, requires_safety_checker=False)避免额外下载并获取未过滤输出用于评测。
  • 设备端随机数生成器 torch.Generator("npu").manual_seed(seed) 可用;注意 NPU 随机数流与 CPU 不同,此处固定 seed 只保证 NPU 内部逐次可复现(非跨设备一致)。同 prompt + 同 seed 25 步生成逐像素可复现(max|Δ|=0)。
  • 生成全程 fp32;HF32(fp32-matmul 的 TF32-like 近似)默认关闭以保证 fp32 确定性,其偏差在一条真实 fp32 UNet 前向上另行实测(见 §9)。

相关获取地址:

  • 权重下载地址(HuggingFace):https://huggingface.co/Lykon/dreamshaper-7
  • 权重下载地址(GitCode 镜像):https://ai.gitcode.com/hf_mirrors/Lykon/dreamshaper-7

2. 验证环境

组件版本
NPUAscend910(65GB HBM)
CANN8.5.1
torch2.9.0+cpu
torch-npu2.9.0.post1
diffusers0.39.0
transformers4.57.6
Python3.11.14

3. 环境准备与权重获取

# 依赖(diffusers 必须 --no-deps,否则会拉入新版 torch 覆盖 torch_npu)
pip install --no-deps diffusers            # 0.39.0
# 其余运行期依赖多数已随 torch_npu 环境预置:transformers / huggingface_hub / safetensors / pillow / numpy

# 权重(约 7.7 GB,含 fp32 + fp16 两套 variant,本脚本用 fp32)。inference.py 内已自包含下载逻辑,缓存为空时自动拉取:
export HF_ENDPOINT=https://hf-mirror.com
python -c "from huggingface_hub import snapshot_download; \
snapshot_download('Lykon/dreamshaper-7', local_dir='$HOME/.cache/models/dreamshaper-7', \
ignore_patterns=['*.onnx','*.h5','*.msgpack','tf_model*','flax_model*'])"

权重目录可用环境变量 dreamshaper_7_MODEL_DIR 或 MODEL_DIR 覆盖,默认 ~/.cache/models/dreamshaper-7。

4. 推理运行

昇腾单卡(本次为 card 0)独占运行,Ascend 编译缓存重定向到 /tmp(NFS 配额安全):

cd /opt/atomgit/deliverables/dreamshaper-7
flock -w 7200 /tmp/npu_card0.lock bash -c '
  ASCEND_RT_VISIBLE_DEVICES=0 ASCEND_CACHE_PATH=/tmp/ascend_cache_dreamshaper-7 \
  ASCEND_PROCESS_LOG_PATH=/tmp/ascend_log ASCEND_WORK_PATH=/tmp/ascend_work \
  python inference.py --device npu '

ASCEND_RT_VISIBLE_DEVICES=0 下进程内该卡即 npu:0,故 inference.py 内统一使用 "npu:0"(可移植)。脚本仅支持 NPU,不提供 --device cpu。

5. Smoke 验证(昇腾 NPU 真机输出)

固定输入:prompt="a photograph of an astronaut riding a horse",seed=12345,num_inference_steps=25,guidance_scale=7.5。

真实 stdout(节选):

=== [Gate 1] 逐子模型 output_loading_info(期望 0/0/0)===
  unet: missing=0 unexpected=0 mismatched=0 params=859,520,964
  vae: missing=0 unexpected=0 mismatched=0 params=83,653,863
  text_encoder: missing=0 unexpected=0 mismatched=0 params=123,060,480
  [Gate 1] PASS (all 0/0/0)

=== 加载 StableDiffusionPipeline (fp32) -> npu:0 ===
  loaded+moved in 7.4s; scheduler=DEISMultistepScheduler
  unet.device=npu:0 vae.device=npu:0 text_encoder.device=npu:0

=== [§5 Smoke] 固定 prompt+seed 多步生成 ===
  generator on: npu
  image size=(512, 512) mode=RGB shape=(512, 512, 3) dtype=uint8
  pixel stats: mean=83.68 std=85.32 min=0 max=255
  saved -> /tmp/dreamshaper-7_out.png
  determinism (same seed x2): max|Δpixel|=0 mean|Δpixel|=0.0000
验证项结果
输出图像512x512 RGB PNG(/tmp/dreamshaper-7_out.png),内容与 prompt 一致(宇航员骑马照片)
25 步生成延迟~2078 ms/image(稳态 p50,含 VAE 解码)
复现性(同 seed 二次)`max

6. 性能参考(仅 NPU)

单图、25 步(num_inference_steps=25、guidance_scale=7.5、含 CFG 双前向),预热 5 次、正式计时 20 次:

指标数值
avg2078.3 ms
min2077.2 ms
max2081.7 ms
p502078.0 ms
p902079.3 ms
p952081.7 ms
吞吐(p50)0.481 img/s
峰值 HBM8616 MB
p95/p501.00(无双峰污染,测量极干净)

7. 精度评测(结构/复现性三证)

文生图任务无 Ground-Truth 图像,采用「定性 + 复现性 + 结构度量」三证,并以随机初始化 UNet 对照组作为决定性功能证据。

  • 定性:预训练管线 25 步生成的图像内容与 prompt 高度吻合(宇航员骑马,连贯自然照片);随机初始化 UNet 生成高频彩色噪声。
  • 复现性:同 prompt+同 seed 二次生成 max|Δpixel|=0(逐像素一致)。
  • 结构度量(Gate 3,决定性):以「平均梯度幅值 grad_mag」区分「自然照片 vs 噪声」——自然照片平滑、grad_mag 小;随机 UNet 输出高频彩噪、grad_mag 大。对随机对照跑 N=3 个不同权重种子,并要求预训练决定性低于每一个随机种子:
对照grad_mag随机/预训练
预训练(正确加载)6.77—
随机 UNet(wseed=0)17.782.63x
随机 UNet(wseed=1)13.742.03x
随机 UNet(wseed=2)13.932.06x
随机均值15.152.24x

结论:预训练模型 grad_mag 决定性地低于全部随机种子(均值 2.24x,逐种子全胜),即预训练产出连贯结构、随机初始化产出噪声 → Gate 3 决定性通过。

注:本模型走多步 DEISMultistepScheduler,即使随机 UNet 的噪声预测也会被多步去噪部分平滑,故 autocorr_lag1(邻域空间自相关)区分度不足(预训练 0.979 vs 随机 ≈0.955,差距小),因此用 grad_mag(高频能量)作为主判别量。

三道加载正确性门禁全部通过:

门禁结果
Gate 1(output_loading_info)UNet / VAE / text_encoder 均 0 missing / 0 unexpected / 0 mismatched
Gate 2(config 落地)cross_attention_dim=768、block_out_channels=[320,640,1280,1280]、attention_head_dim=8 等 9 项关键结构键全部生效一致;scheduler=DEISMultistepScheduler
Gate 3(随机对照)grad_mag 预训练 6.77 vs 随机均值 15.15(2.24x,逐种子全胜)→ 决定性通过

8. 适配截图

  • agent_workflow
  • npu_device_call
  • model_result

9. 注意事项

最易踩的坑:ASCEND_CACHE_PATH 目录缺失会伪装成 HF32/ACL error 500001。

  • 现象:加载或首帧编译阶段崩溃。
  • 关键报错原文:AclSetCompileopt ... error 500001。
  • 根因:ASCEND_CACHE_PATH 指向的目录若不存在,GE/AOE 初始化失败会伪装成 HF32/ACL 报错,误导排查方向。
  • 处理:脚本在 import 期即 os.makedirs(..., exist_ok=True) 预建。

其余事项:

  1. 强制 fp32 保正确性:config 提供 fp16/fp32 两套 variant,为正确性对照本脚本强制 torch_dtype=torch.float32(不传 variant,加载 model.safetensors);7.7 GB fp32 权重在 65 GB HBM 下峰值仅 8616 MB,无需回落 fp16。
  2. NPU 随机数流与 CPU 不同:torch.Generator("npu").manual_seed(seed) 只保证 NPU 内部逐次可复现(同 seed 二次 max|Δpixel|=0),不保证与 CPU/GPU 跨设备逐像素一致;README 已如实标注。
  3. HF32 偏差实测:生成全程 fp32,脚本默认关闭 HF32(torch.npu.matmul.allow_hf32=False、torch.npu.conv.allow_hf32=False)保证 fp32 确定性;在一条真实 fp32 UNet 前向上实测 HF32 on/off max|Δ(sample)| = 6.05e-04(相对 1.57e-4),量级极小。
  4. safety_checker 已关闭:脚本设 safety_checker=None, requires_safety_checker=False 以避免额外下载并获取未过滤输出用于评测;公开服务场景请自行开启。
  5. torch_dtype 弃用提示可忽略:diffusers 0.39.0 会打印「torch_dtype is deprecated! Use dtype instead!」,但模型级 from_pretrained 实际仍只接受 torch_dtype,忽略该提示即可。

10. 标签

#NPU #Ascend