HiDream-O1-Image を 3〜8 倍速く使う: steps / CFG / 解像度の実測ベンチ

#hidream#diffusion#imagegeneration#benchmark#gpu

TL;DR

HiDream-O1-Image Full をローカル常駐サーバーに載せて Studio UI に統合した。公式レシピ相当の 2048x2048 / 50 steps / guidance 5.0 は綺麗だが、1 枚 33 秒前後かかる。アイデア検証で毎回これを回すのは重い。

そこで同一 prompt / 同一 seed で stepsguidance、解像度を振ったところ、実用上かなり使いやすい落とし所が見えた。

設定実測公式相当比
2048 / 50 steps / g533.37s1.00x
2048 / 28 steps / g518.41s1.81x
1536 / 20 steps / g57.14s4.67x
1024 / 20 steps / g53.83s8.71x

結論として、最初は低解像度・低 steps で方向性を探り、最後だけ高品質で焼くのがよさそう。特に 1536x1536 / 28-36 steps は、速度と品質のバランスがかなり良い。


動機

画像生成を UI に組み込むと、モデルの絶対品質よりも「試行錯誤の回転速度」が重要になる。

一発で完成画像を出すよりも、実際にはこういう流れになる。

  1. 構図・雰囲気・衣装・背景の方向性を見る
  2. prompt を少し直す
  3. seed を変える
  4. 良さそうな候補だけ高品質で出し直す

公式レシピのまま毎回 30 秒以上待つと、このループが重い。逆に 5〜10 秒で粗い候補を見られるなら、体感はかなり変わる。

今回の目的は「最高品質の 1 枚」ではなく、品質を大きく壊さずに探索コストをどこまで下げられるかを把握すること。


環境

  • GPU: NVIDIA RTX PRO 6000 Blackwell Max-Q (96 GB VRAM)
  • モデル: HiDream-O1-Image Full (8B, bf16)
  • 推論サーバー: 自前 Python HTTP server、モデル常駐
  • 計測対象: model load 後の /generate/t2i 1 リクエスト
  • seed: 42
  • prompt:
A cinematic portrait photo of a woman in a rainy neon street,
detailed skin, 85mm lens, realistic lighting, high detail

比較画像はすべてこの prompt と seed を固定している。変えたのは stepsguidance_scale、解像度、resolution snapping の有無だけ。

項目
promptA cinematic portrait photo of a woman in a rainy neon street, detailed skin, 85mm lens, realistic lighting, high detail
seed42
modet2i
dtypebf16
negative promptなし
sampler / schedulerHiDream pipeline デフォルト

人物ポートレートを使った理由は、髪・肌・背景光・ディテールがそこそこ見やすいから。ただし若い女性の顔はもともとシワや凹凸が少ないので、低 steps の弱点が出にくい素材でもある。この点は後述する。

記事中の画像は、生成結果を横に並べた contact sheet にしている。細部比較は原寸の方が分かりやすいが、UI の探索用途ではまず「ぱっと見で候補として残せるか」が大事なので、この記事では一覧性を優先した。


まず steps を下げる

guidance=5.0、解像度 2048x2048 固定で steps だけ下げた。

steps

ResolutionStepsGuidanceElapsedSpeedup vs 50 steps
2048x2048205.013.070s2.55x
2048x2048285.018.412s1.81x
2048x2048365.023.854s1.40x
2048x2048505.033.370s1.00x

ほぼ理論値通り。HiDream のこの経路では、guidance > 1.0 のとき conditional / unconditional の 2 forward が走るので、steps を下げれば素直に速くなる。

見た目は、20 steps まで落とすと少し粗い。28 steps は比較すると細部の薄さが見えるが、ぱっと見ではかなり耐える。36 steps は多くの用途で十分そう。


guidance=1.0 はかなり速い

次に guidance も含めて、実用プリセット候補を比べた。

presets

PresetResolutionStepsGuidanceCFGElapsed
Draft2048x2048241.0off8.164s
Balanced2048x2048363.0on23.664s
Official2048x2048505.0on32.609s

guidance=1.0 は CFG が実質オフになるので、step 数以上に速い。24 steps でも 8 秒台。

ただし guidance を下げると prompt adherence や絵作りは変わる。アイデア検証には良いが、「文字」「細かい衣装指定」「複数要素の正確な配置」みたいなケースでは guidance=3-5 の方が安心。


解像度指定の罠: 1024 を指定しても速くならない

最初は単純に width=1024, height=1024 を渡せば速くなると思っていた。だが公式 pipeline は指定解像度をそのまま使わず、近いアスペクト比の固定バケットにスナップする。

buckets

実測するとこうなる。

RequestedActual
512x5122048x2048
1024x10242048x2048
2048x20482048x2048
1280x7202560x1440
720x12801440x2560
1024x7682304x1728

つまり、単に UI から 1024x1024 を送っても速くならない。正方形なら結局 2048x2048 で生成される。

コード上は models/utils.pyPREDEFINED_RESOLUTIONS に寄せているだけなので、品質の安定性を優先した設計だと思う。


バケットを外して低解像度生成する

実験用に snap_resolution=false を追加し、pipeline の resolution snapping を bypass できるようにした。安全のため、任意解像度は次の条件に制限した。

  • width / height は 32px アライン
  • 256px 以上
  • 合計 4.3MP 以下

20 steps / guidance=5.01024 / 1536 / 2048 を比べる。

resolution

ResolutionElapsedSpeedup vs 2048
1024x10243.831s3.47x
1536x15367.139s1.86x
2048x204813.278s1.00x

これはかなり効いた。2048 の公式寄り生成が 30 秒台だったことを考えると、1536 + 28 steps あたりは 10 秒前後まで落ちる見込みがある。体感としては別物。

1024 は速いが、情報量はかなり落ちる。方向性確認には良いが、最終出力として常用するには粗さが気になる場面が増えそう。


Studio のプリセットに落とす

今回の結果をもとに、Studio UI ではこういう設定にした。

用途解像度stepsguidance使い方
高速プレビュー1024x102420-241.0-3.0構図・雰囲気チェック
標準1536x153628-363.0-5.0普段使い
高品質2048x204836-505.0採用候補の出し直し
公式 bucketbucket505.0upstream recipe に寄せる

UI では steps と解像度を別々に選べるようにした。これで、アイデア検証時は 1024 / 24 steps で回し、良さそうなら同じ prompt / seed を 15362048 で焼き直す流れが作れる。


品質劣化が出やすいケース

今回のポートレートでは、28 steps と 50 steps の差は「比較すれば分かる」程度だった。だがこれは素材にも助けられている。

低 steps / 低解像度の弱点が出やすいのは、たぶん次のようなケース。

  • 高齢者の顔、シワ、肌の凹凸
  • 手、指、アクセサリー
  • 細かい柄の服
  • 看板や本の文字
  • 複数人物
  • 背景の小物が多い室内

逆に、若い人物の顔、シンプルな背景、柔らかいライティングでは低コスト設定でも破綻が目立ちにくい。

なので本番プリセットは 1 つに固定するより、対象に応じてユーザーが探索コストを選べる方がよい。


再現コマンド

ベンチスクリプトは image_server/bench_quality_speed.py に置いた。モデルを常駐ロードした後、HTTP API 経由で叩くので、model load time は測定に含まれない。

./image_server/start_image_server.sh

steps 比較:

python3 image_server/bench_quality_speed.py \
  --prompt "A cinematic portrait photo of a woman in a rainy neon street, detailed skin, 85mm lens, realistic lighting, high detail" \
  --seed 42 \
  --variant s20_g5,20,5 \
  --variant s28_g5,28,5 \
  --variant s36_g5,36,5 \
  --variant s50_g5,50,5

解像度比較:

python3 image_server/bench_quality_speed.py \
  --prompt "A cinematic portrait photo of a woman in a rainy neon street, detailed skin, 85mm lens, realistic lighting, high detail" \
  --seed 42 \
  --variant s20_g5,20,5 \
  --size 1024x1024 \
  --size 1536x1536 \
  --size 2048x2048 \
  --no-snap-resolution

まとめ

HiDream-O1-Image Full は公式レシピのままだと高品質だが、試行錯誤には重い。だが steps、CFG、解像度を分けて見ると、かなり素直に高速化できる。

  • steps はほぼ線形に効く
  • guidance=1.0 は CFG が外れてかなり速い
  • 公式 pipeline は解像度を固定 bucket にスナップする
  • 本当に低解像度で生成すると、1024/1536 は大きく速い
  • 実用上は 1536 / 28-36 steps が良いバランス候補

画像生成 UI は「最初から最高品質」より、低コスト探索 → 高品質確定出力の導線を作る方が使いやすい。今回の実験で、その設計にかなり自信が持てた。