RTX 5070 Tiでローカル画像生成:SD-Turboを1・2・4・8 stepで実測

実験日: 2026-08-24
環境: RTX 5070 Ti 16GB / WSL2 / PyTorch 2.13.0+cu130 / Diffusers 0.40.0

生成AIを理解するには、promptをweb serviceへ入力するだけでなく、modelをlocal GPUへloadし、seed、denoising step、VRAM、latencyを測ると仕組みが見えます。

stepを増やせば必ず画像が良くなるとは限りません。待ち時間との釣り合いも確認します。

公開modelstabilityai/sd-turboをこのPCへdownloadし、512×512、FP16、guidance scale 0、seed 42で1・2・4・8 stepを実行しました。warmup後5回の中央値は0.092、0.117、0.166、0.254秒。PyTorch peak allocatedは全条件約3,120 MiBでした。

同じ4 step・seed 42を再実行するとpixel SHA-256が完全一致し、seed 43では別画像になりました。ただし同じseedの再現性はsoftware、driver、hardwareを変えてまで保証する結果ではありません。

1・2・4・8 stepの結果

steps 中央値 5回範囲 peak allocated
1 0.092秒 0.088~0.096秒 3,120.5 MiB
2 0.117秒 0.112~0.117秒 3,120.5 MiB
4 0.166秒 0.155~0.188秒 3,120.5 MiB
8 0.254秒 0.249~0.257秒 3,120.5 MiB
SD-TurboをRTX 5070 Tiで1・2・4・8 stepローカル生成した比較
SD-TurboをRTX 5070 Tiで1・2・4・8 stepローカル生成した比較

4 stepの生成結果です。

SD-TurboをRTX 5070 Tiで4 step、seed 42により生成した大学AI研究室の画像
SD-TurboをRTX 5070 Tiで4 step、seed 42により生成した大学AI研究室の画像

画像を目視すると、stepを増やすほど単調に品質が上がるとは言えません。SD-Turboは少step向けにdistillされたmodelで、8 stepは「高品質設定」と同義ではありません。

実際にdownloadしたもの

Python packageをWSL venvへ入れました。

source /opt/ai-lab/venv/bin/activate
pip install diffusers transformers accelerate safetensors sentencepiece

実行versionです。

diffusers     0.40.0
transformers  5.15.1
accelerate    1.14.0
safetensors   0.8.0
torch         2.13.0+cu130

modelはDiffusersがstabilityai/sd-turboから取得し、Hugging Face cacheへ保存しました。初回は12 fileの取得に約31秒、pipeline loadを含むscript上のload時間は33.9秒でした。

2回目はcacheから読み、load時間2.63秒です。画像1枚の0.1~0.3秒だけを見ても、初回downloadとmodel loadを含むuser experienceは説明できません。

pipelineをGPUへ載せる

pipe = AutoPipelineForText2Image.from_pretrained(
    "stabilityai/sd-turbo",
    torch_dtype=torch.float16,
    variant="fp16",
)
pipe = pipe.to("cuda")

FP16を使うとFP32よりweight memoryを減らせます。今回のtorch_dtype引数には将来dtypeへ変更するdeprecation warningが出ました。warningを記録し、versionを固定しています。

DiffusersのAutoPipelineはmodel configから適切なtext-to-image pipelineを選びます。この実行ではStableDiffusionPipelineが構成されました。

promptを固定する

全条件で同じ英語promptを使いました。

A small university AI laboratory desk,
a black GPU workstation beside notebooks with neural network diagrams,
warm morning light, realistic editorial photograph,
no text, no logo

比較中にpromptを変えると、step差とprompt差を分離できません。negative promptは使っていません。

no text, no logoと書いても完全な保証にはなりません。実際の比較画像にはmonitor上に文字のような模様があります。生成modelはinstructionを論理constraintとして実行するわけではありません。

guidance scaleを0にする

生成callです。

image = pipe(
    prompt,
    num_inference_steps=4,
    guidance_scale=0.0,
    height=512,
    width=512,
    generator=generator,
).images[0]

SD-Turboのmodel cardは1~4 stepの高速生成とguidance_scale=0.0を例示しています。普通のStable Diffusionでよく見る7.5をそのまま使わず、model固有の推奨条件へ合わせました。

model familyが違えば適切なscheduler、step、guidanceも変わります。「Stable Diffusionの設定」を一括りにできません。

seedはCUDA Generatorへ渡す

generator = torch.Generator(device="cuda").manual_seed(42)

diffusion modelはrandom noiseから生成を始めます。seedを固定すると初期noiseを固定でき、step数だけを変える比較がしやすくなります。

global torch.manual_seedだけに頼らず、生成call専用Generatorを作りました。各測定replicateでもseed 42から作り直しています。

warmupを測定から外す

最初のdiagnostic runでは1 stepが0.790秒、2 stepが0.127秒でした。1 stepの方が大幅に遅いのは不自然です。

原因は最初のcallにCUDA initializationやkernel setupが含まれたためです。そこでseed 999で1回warmupし、その後各stepを5回測り直しました。

pipe(prompt, num_inference_steps=1, generator=warmup_generator)

for _ in range(5):
    torch.cuda.synchronize()
    started = time.perf_counter()
    image = pipe(...)
    torch.cuda.synchronize()
    samples.append(time.perf_counter() - started)

この修正で1 step中央値は0.092秒になりました。GPU benchmarkではwarmupとsynchronize()が不可欠です。CUDA operationは非同期なので、同期せずCPU clockだけ測ると処理完了前にtimerが止まります。

step数と時間はほぼ増える

1 step  0.092 s
2 steps 0.117 s
4 steps 0.166 s
8 steps 0.254 s

1→8 stepでUNet evaluation回数は8倍ですが、end-to-end時間は2.76倍でした。text encoding、VAE decode、Python callなどstep数に依存しない固定costがあるためです。

画像/秒へ単純換算すると次です。

1 step  約10.84 images/s
2 steps  約 8.56 images/s
4 steps  約 6.04 images/s
8 steps  約 3.93 images/s

これはbatch 1、512×512、同じpipelineをload済みのthroughputです。model load、PNG保存、web deliveryは含みません。

peak memoryがstep数で変わらなかった理由

全条件のtorch.cuda.max_memory_allocated()は約3,120.5 MiBでした。

denoising stepを増やしても、同じshapeのlatentとmodel weightを順番に再利用します。計算回数は増えても、同時に保持するtensorの最大構成が同じならpeakは増えません。

一方、resolutionやbatchを増やすとactivation tensorが大きくなり、peak memoryは増えます。step数は主にtime、resolutionとbatchはtimeとmemoryの両方へ効く、という違いです。

この3,120 MiBはPyTorch allocatorのallocated peakです。driver contextや他processを含むnvidia-smi値とは一致しません。

1・2・4・8 stepを目視比較する

全画像は同じseed 42ですが、scheduler trajectoryがstep数で変わるため別pixelになります。

1 stepでもdesk、monitor、rackらしい構図は出ています。2~4 stepではobjectの輪郭や配置が変わり、8 stepでは色の強いmonitorや本が増えました。

ただし「8 stepが最高」と客観評価していません。prompt adherence、美観、artifactは人によって判断が変わります。1 prompt×1 seedだけではquality benchmarkになりません。

定量化するなら次が必要です。

  • 複数prompt category
  • 各prompt複数seed
  • human preference blind test
  • CLIPなどのtext-image alignment
  • artifactや文字崩れのannotation
  • generation失敗率

この記事の画像は、実行条件差を人間が確認するqualitative evidenceです。

同じseedはpixel単位で一致した

4 step、seed 42を同じprocessで再実行しました。PIL imageのpixel byte列へSHA-256を計算します。

hashlib.sha256(image.tobytes()).hexdigest()

2回とも次のhashでした。

deb671cd10d3abd2a64944305de5011efbec9ba74efefd161c2eb704f2f62d9e

pixel単位で完全一致です。PNG file sizeも両方409,308 bytesでした。

seed 43は別hashになりました。

30959d7387faa9fcc42bb055a8f59702a0bac98b742983c17a2769078f3ca058

ただしPyTorch、Diffusers、CUDA、scheduler、GPU architectureを変えると、同じseedでも同一pixelにならない可能性があります。seedは実験条件の一部であり、普遍的な画像IDではありません。

safety checker warningをどう扱ったか

pipeline load時、safety checkerが無効であるというwarningが出ました。公開serviceでunfiltered resultをそのまま配信しないようDiffusersが注意しています。

今回は自分のoffline experimentで、promptは研究室の机です。生成6枚を保存後に目視確認し、公開する比較gridと4-step画像に不適切内容や実在人物の描写がないことを確認しました。

不特定userのpromptを受けるserviceなら、content policy、input/output filter、rate limit、audit log、人間review、model license確認が必要です。

download元とlicenseを記録する

localで動くことと、自由に再配布できることは同じではありません。model cardとlicenseを確認し、model IDを結果JSONへ保存しました。

{
  "model": "stabilityai/sd-turbo",
  "dtype": "float16",
  "resolution": [512, 512],
  "guidance_scale": 0.0
}

研究成果へ画像を使う場合は、model licenseだけでなくdataset由来のrisk、生成物の扱い、所属機関のruleも確認します。

再現手順

source /opt/ai-lab/venv/bin/activate

cd /mnt/c/Users/user/Documents/Codex/2026-08-24/ko/work/ai_lab
python -u experiment_local_image_generation.py

artifactです。

work/ai_lab/experiment_local_image_generation.py
work/ai_lab/results/local_image_generation.json
work/ai_lab/generated_images/sd_turbo_steps1_seed42.png
work/ai_lab/generated_images/sd_turbo_steps2_seed42.png
work/ai_lab/generated_images/sd_turbo_steps4_seed42.png
work/ai_lab/generated_images/sd_turbo_steps8_seed42.png
work/ai_lab/generated_images/sd_turbo_steps4_seed42_repeat.png
work/ai_lab/generated_images/sd_turbo_steps4_seed43_different_seed.png
work/figures/sd-turbo-local-steps.png

JSONにはload時間、prompt、version、GPU、各5回のraw秒、median、peak allocated、pixel hash、PNG sizeを保存しています。

結論

RTX 5070 Ti 16GBとWSL2でSD-Turboをlocal実行し、512×512画像をwarm状態で約0.09~0.25秒で生成できました。peak PyTorch allocationは約3.05 GiBで、16GB VRAMには余裕があります。

しかし速さだけが結果ではありません。初回downloadは31秒、pipeline loadはcache後でも2.63秒かかります。1 stepの最初の測定はwarmup不足で0.79秒となり、測定設計を直す必要がありました。

同じseed・条件ではpixel一致を確認できましたが、step数を増やしても品質が単調に上がる保証はありません。local画像生成も、model ID、prompt、seed、scheduler条件、warmup、raw timing、目視確認を揃えると、再現可能なexperimentになります。

関連記事