HelloSun's picture
docs: restructure README/REPORT and clean metadata
b8c0cd7
|
Raw History Blame Contribute Delete
7.82 kB
# Stable Diffusion 3.5 Medium — OpenVINO INT4:轉換與實測報告
| 項目 | 內容 |
| --- | --- |
| **來源模型** | [`stabilityai/stable-diffusion-3.5-medium`](https://huggingface.co/stabilityai/stable-diffusion-3.5-medium) |
| **Pipeline 類型** | `StableDiffusion3Pipeline` |
| **Scheduler** | `FlowMatchEulerDiscreteScheduler`(`shift=3.0`) |
| **目標格式** | OpenVINO IR;Transformer 與 T5 text encoder 為 INT4,其餘為 INT8 |
| **發布位置** | [`HelloSun/SD3.5-medium-OpenVINO-INT4`](https://huggingface.co/HelloSun/SD3.5-medium-OpenVINO-INT4) |
---
## 目錄
1. 環境與版本
2. 轉換流程
3. 模型檔案與體積
4. 實測結果
5. 測試 Prompt
6. 觀察與結論
7. 復現步驟
## 1. 環境與版本
```text
diffusers==0.37.1 transformers==4.57.6 tokenizers==0.22.0 huggingface-hub==0.35.1 optimum==2.3.0 optimum-intel==2.2.0 openvino==2026.4.0 nncf==3.4.0 torch pillow psutil sentencepiece accelerate
```
## 2. 轉換流程
### 步驟 1 — 匯出 OpenVINO FP16
```bash
optimum-cli export openvino -m stabilityai/stable-diffusion-3.5-medium --task text-to-image --library diffusers --weight-format fp16 ./SD3.5-medium-ov-fp16
```
### 步驟 2 — NNCF weight-only 量化
由 [`quantize_int4.py`](quantize_int4.py) 執行。
```python
from optimum.intel.openvino.configuration import (
OVConfig, OVWeightQuantizationConfig, OVPipelineQuantizationConfig,
)
int4_config = OVWeightQuantizationConfig(
bits=4, sym=False, group_size=128,
group_size_fallback="adjust", ratio=1.0,
)
pipeline_config = OVPipelineQuantizationConfig(
quantization_configs={
"transformer": int4_config,
"text_encoder_3": int4_config,
},
default_config=OVWeightQuantizationConfig(bits=8),
)
```
**重點說明**
- `bits=4`、`sym=False` → **非對稱 4-bit** weight-only 量化。
- `group_size=128` → 每 128 個權重共用一組 scale / zero-point。
- `group_size_fallback="adjust"` → 分組不整除時自動調整群組大小,避免部分層被跳過。
- `ratio=1.0` → 全部權重都量化,不做混合精度保留。
- 未被列出的元件(VAE、vision encoder 等)沿用 `default_config` 的 INT8。
- **注意**:`openvino_config.json` 的 `default_config` 只記錄 `quant_method`,未寫入 `bits=8`;INT8 fallback 只能從 `quantize_int4.py` 得知。
## 3. 模型檔案與體積
| 元件 | 精度 | 說明 |
| --- | --- | --- |
| `transformer` | **INT4** | |
| `text_encoder_3` | **INT4** | |
| `vae_decoder` | INT8 | 由 latent 解回 RGB |
| `vae_encoder` | INT8 | image encoder(推論時未實際使用) |
| `tokenizer / processor` | — | 未量化 |
| `scheduler` | — | 設定取自 `scheduler/scheduler_config.json` |
### 實際體積
下表為 repo 內 `openvino_model.bin` 的實際位元組數(Git LFS 記錄值),可直接對照下載量。
| 元件 | 位元組 | GB | GiB |
| --- | ---: | ---: | ---: |
| `text_encoder_3` | 2,557,956,630 | 2.56 GB | 2.38 GiB |
| `transformer` | 1,620,333,792 | 1.62 GB | 1.51 GiB |
| `text_encoder_2` | 696,453,879 | 0.70 GB | 0.65 GiB |
| `text_encoder` | 124,172,025 | 0.12 GB | 0.12 GiB |
| `vae_decoder` | 49,627,579 | 0.05 GB | 0.05 GiB |
| `vae_encoder` | 34,337,212 | 0.03 GB | 0.03 GiB |
| **合計** | **5,082,881,117** | **5.08 GB** | **4.73 GiB** |
FP16 匯出模型約 **15.17 GB**(transformer 4.60 GB + text_encoder_3 8.87 GB + text_encoder 0.23 GB + text_encoder_2 1.30 GB + vae 0.15 GB)——取自原始轉換紀錄。
INT8 部分(兩個 CLIP text encoder 與 VAE)為 **1.72 GB**,佔 INT4 總量的 34%。
**⚠️ `outputs/benchmark_quantization.json` 記錄的 `int4_size_gb` 為 `4.76`,與 repo 內實際位元組總和 5.08 GB 不符**;引用時請以本表為準。
## 4. 實測結果
| 項目 | 數值 |
| --- | --- |
| 樣本數 | 5 |
| 推論設定 | `num_inference_steps=40`、`guidance_scale=4.5`、1024×1024 |
| `from_pretrained` + `compile=True` | **8.72 s** |
| 平均總耗時 | **226.03 s** |
| 平均單步耗時 | 5.65 s |
| 記憶體高水位 | 3,276.2 MB(來源:`/proc/self/status VmHWM`) |
### 逐張結果
| # | Prompt | Seed | steps | CFG | 總耗時 (s) | 平均單步 (s) | 逐 step 耗時 (s) |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 01_hanfu | 42 | 40 | guidance_scale=None | 228.41 | 5.710 | — |
| 02_astronaut | 43 | 40 | guidance_scale=None | 228.58 | 5.710 | — |
| 03_taipei | 44 | 40 | guidance_scale=None | 224.70 | 5.620 | — |
| 04_shiba | 45 | 40 | guidance_scale=None | 222.18 | 5.550 | — |
| 05_ink | 46 | 40 | guidance_scale=None | 226.27 | 5.660 | — |
| **平均** | | | | **226.03** | **5.650** | |
### 逐 step 耗時(主測組)
| # | Prompt | Seed | 總耗時 (s) | 平均單步 (s) | 逐 step 耗時 (s) |
| --- | --- | --- | ---: | ---: | --- |
| 01 | hanfu | 42 | 228.41 | 5.710 | — |
| 02 | astronaut | 43 | 228.58 | 5.710 | — |
| 03 | taipei | 44 | 224.70 | 5.620 | — |
| 04 | shiba | 45 | 222.18 | 5.550 | — |
| 05 | ink | 46 | 226.27 | 5.660 | — |
> 「總耗時」包含文字編碼與 VAE decode;「平均單步」= 逐 step 耗時加總 ÷ 步數,
> 因此會略小於 `總耗時 ÷ 步數`。
## 5. 測試 Prompt
| # | Seed | Prompt |
| --- | --- | --- |
| 01 | 42 | `Young Chinese woman in red Hanfu, intricate embroidery, impeccable makeup, red floral forehead pattern, elaborate high bun, golden phoenix headdress, soft-lit outdoor night background, silhouetted tiered pagoda, blurred colorful distant lights, photorealistic, ultra detailed, 8k` |
| 02 | 43 | `Astronaut in a jungle, cold color palette, muted colors, detailed, 8k, photorealistic, cinematic lighting` |
| 03 | 44 | `Cyberpunk street in Taipei at night, heavy rain, neon signs with text 'TAIPEI' and Chinese characters '台北', reflections on wet asphalt, crowded night market, cinematic, ultra detailed` |
| 04 | 45 | `Cute Shiba Inu wearing a tiny astronaut helmet, sitting in a field of sunflowers under a starry sky, dreamy illustration, vibrant colors, high quality` |
| 05 | 46 | `Traditional Chinese ink wash landscape, misty mountains, a small pagoda on a cliff, cranes flying, minimalist, elegant, high aesthetic quality` |
完整內容另見 [`outputs/prompts.txt`](outputs/prompts.txt)。
## 6. 觀察與結論
1. **記憶體極低**:peak RSS 僅 3.28 GB(取自 `/proc/self/status` 的 `VmHWM`),明顯低於其他 Transformer 架構的 repo——因為 text encoder 已被 INT4 量化且只有 40 步中的一次性編碼。
2. **各張耗時非常一致**:222.18–228.58 s,離散度不到 3%,顯示 40 步的流程已完全去除 cold-start 效應。
3. **40 steps 的成本遠高於同級蒸餾模型**:平均單步 5.65 s,但總步數是 FLUX.2-klein(4 步)的 10 倍,導致總時間為其 6.4 倍。
4. **`peak_rss_mb` 五張完全相同(3276.2)**:`VmHWM` 是單調遞增的行程級高水位標記,並非五次獨立量測。
## 7. 復現步驟
```bash
# 1. 匯出 FP16 OpenVINO 模型
optimum-cli export openvino \
-m stabilityai/stable-diffusion-3.5-medium \
--task text-to-image \
--library diffusers \
--weight-format fp16 \
./SD3.5-medium-ov-fp16
# 2. NNCF weight-only INT4 量化
python quantize_int4.py --fp16-dir ./SD3.5-medium-ov-fp16 \
--int4-dir ./SD3.5-medium-ov-int4
# 3. 單張推論
python inference_int4.py
# 4. 批次生成 5 組 + benchmark
python generate5.py --outdir outputs
```
量化腳本會另外輸出:
- [`outputs/benchmark.json`](outputs/benchmark.json) — 逐 step 耗時、記憶體、系統資訊
- [`outputs/prompts.txt`](outputs/prompts.txt) — prompt 與 seed 清單
- `outputs/*.png` — 主測組 1024px 與對照組 512px
---
原始機器紀錄為 [`outputs/benchmark.json`](outputs/benchmark.json)。