Jetson Orin NanoでStable Diffusionを動かす!画像生成入門【TensorRT最適化】

Jetson Orin NanoでStable Diffusionを動かす!画像生成入門【TensorRT最適化】

Jetson Orin NanoでStable Diffusionを動かしたいけれど、メモリ不足やビルドエラーで挫折した経験はないだろうか。この記事では実機を使った手順と、TensorRTで高速化する方法をまとめて解説する。

この記事でわかること

  • Jetson Orin NanoでStable Diffusionを動作させるための環境構築手順
  • メモリ不足を回避するためのスワップ設定と最適化のコツ
  • TensorRTを使ってエンジンファイルを作成し、推論を高速化する方法
  • 実機で計測した生成速度の目安
  • 動作環境と必要なもの

    今回の検証環境は以下の通りだ。

    | 項目 | 内容 |

    |——|——|

    | ボード | Jetson Orin Nano Super 8GB |

    | JetPack | 6.2 (L4T 36.4.3) |

    | ストレージ | NVMe SSD 512GB |

    | モデル | Stable Diffusion v1.5 |

    Jetson Orin Nano Superは67 TOPS (INT8)の高性能で8GB LPDDR5メモリを搭載。4GBモデルは避け、8GBモデルを強く推奨する。ユニファイドメモリ構造のため、SD v1.5でも安定動作が可能だ。

    ストレージはモデルファイルが数GBあるため、NVMe SSD Western Digital SN770 500GB NVMe(Amazon) を使うことを前提にしている。microSDカード Samsung microSDXC 128GB (Endurance)(Amazon) でも動作はするが、モデルのロード時間が大幅に伸びるため実用的ではない。

    スワップ領域の設定(必須)

    Jetson Orin Nanoは物理メモリとGPUメモリが共有されているため、Stable Diffusionの動作中にメモリが枯渇しやすい。まず最初にスワップを増やしておく。

    デフォルトのスワップサイズを確認する。

    
    free -h
    

    スワップが2GB程度しかない場合は以下の手順で8GBに拡張する。

    
    # 既存のスワップを無効化
    sudo swapoff -a
    
    # 8GBのスワップファイルを作成
    sudo fallocate -l 8G /mnt/swapfile
    sudo chmod 600 /mnt/swapfile
    sudo mkswap /mnt/swapfile
    sudo swapon /mnt/swapfile
    
    # 再起動後も有効にする
    echo '/mnt/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
    

    スワップはNVMe SSD上に置くことで読み書き速度を確保できる。

    環境構築:Pythonと依存ライブラリのインストール

    仮想環境の準備

    システムのPythonを汚さないために仮想環境を使う。

    
    sudo apt update
    sudo apt install -y python3-pip python3-venv
    
    python3 -m venv ~/sd_env
    source ~/sd_env/bin/activate
    

    PyTorchのインストール

    Jetson向けのPyTorchはNVIDIAが公式ビルドを提供している。通常のpipではARM+CUDA対応のバイナリが入らないため、必ずNVIDIAのリポジトリから取得する。

    
    pip install --upgrade pip
    
    # JetPack 6.2 / PyTorch 2.4対応版
    pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121
    

    インストール後、CUDAが認識されているかを確認する。

    
    python3 -c "import torch; print(torch.cuda.is_available()); print(torch.version.cuda)"
    

    True と表示されれば成功だ。

    diffusersと関連ライブラリのインストール

    
    pip install diffusers transformers accelerate safetensors
    pip install opencv-python Pillow
    

    Stable Diffusionの動作確認(シンプル版)

    まずTensorRT最適化なしの素の状態で動作確認する。

    
    # generate_simple.py
    from diffusers import StableDiffusionPipeline
    import torch
    
    model_id = "runwayml/stable-diffusion-v1-5"
    
    pipe = StableDiffusionPipeline.from_pretrained(
        model_id,
        torch_dtype=torch.float16,
        safety_checker=None,
    )
    pipe = pipe.to("cuda")
    
    # メモリ最適化
    pipe.enable_attention_slicing()
    
    prompt = "a photo of a cat on a sunny beach, high quality"
    image = pipe(prompt, num_inference_steps=20).images[0]
    image.save("output.png")
    print("生成完了")
    
    
    python3 generate_simple.py
    

    初回実行時はHugging Faceからモデルがダウンロードされるためネット接続が必要だ。モデルのサイズは約4GBある。

    この状態での生成速度は筆者の環境で512×512・20ステップあたり約70秒だった。実用には厳しい速度なので、次のステップでTensorRT最適化を行う。

    TensorRTによる高速化

    TensorRTのインストール確認

    JetPack 6.2にはTensorRT 10.xが含まれているため、追加インストールは不要なことが多い。バージョンを確認する。

    
    dpkg -l | grep tensorrt
    python3 -c "import tensorrt; print(tensorrt.__version__)"
    

    TensorRTビルド時にメモリ不足やlayernorm警告が出る場合は、ONNX opset 17以上でモデルを再エクスポートすると安定する。

    torch2trtのインストール

    UNetをTensorRTエンジンに変換するために torch2trt を使う。

    
    cd ~
    git clone https://github.com/NVIDIA-AI-IOT/torch2trt
    cd torch2trt
    pip install .
    

    ビルドには10〜15分かかる。エラーが出る場合は cuda-toolkit の開発ヘッダが不足している場合が多い。

    
    sudo apt install -y cuda-toolkit-12-4
    

    TensorRTエンジンの変換スクリプト

    
    # convert_trt.py
    import torch
    from diffusers import StableDiffusionPipeline
    from torch2trt import torch2trt
    
    model_id = "runwayml/stable-diffusion-v1-5"
    
    pipe = StableDiffusionPipeline.from_pretrained(
        model_id,
        torch_dtype=torch.float16,
        safety_checker=None,
    )
    pipe = pipe.to("cuda")
    
    # UNetのTensorRT変換
    unet = pipe.unet
    unet.eval()
    
    # ダミー入力の作成(512x512、バッチサイズ1)
    sample = torch.randn(2, 4, 64, 64).half().cuda()
    timestep = torch.tensor([1]).cuda()
    encoder_hidden = torch.randn(2, 77, 768).half().cuda()
    
    print("TensorRT変換を開始します(10〜20分かかります)")
    unet_trt = torch2trt(
        unet,
        [sample, timestep, encoder_hidden],
        fp16_mode=True,
        max_batch_size=2,
    )
    
    torch.save(unet_trt.state_dict(), "unet_trt.pth")
    print("変換完了: unet_trt.pth を保存しました")
    
    
    python3 convert_trt.py
    

    変換中はGPU使用率が100%に張り付く。冷却ファン Noctua NF-A4x10 5V PWMファン(Amazon) をしっかり取り付けていないとサーマルスロットリングが発生するため注意が必要だ。

    TensorRTエンジンを使った推論

    
    # generate_trt.py
    from diffusers import StableDiffusionPipeline
    from torch2trt import TRTModule
    import torch
    
    model_id = "runwayml/stable-diffusion-v1-5"
    
    pipe = StableDiffusionPipeline.from_pretrained(
        model_id,
        torch_dtype=torch.float16,
        safety_checker=None,
    )
    pipe = pipe.to("cuda")
    
    # TRTエンジンに差し替え
    unet_trt = TRTModule()
    unet_trt.load_state_dict(torch.load("unet_trt.pth"))
    pipe.unet = unet_trt
    
    prompt = "a photo of a cat on a sunny beach, high quality"
    image = pipe(prompt, num_inference_steps=20).images[0]
    image.save("output_trt.png")
    print("TRT推論完了")
    
    
    python3 generate_trt.py
    

    実測パフォーマンス比較

    筆者の環境で計測した結果を以下に示す。

    | 条件 | 生成時間(512×512, 20step) |

    |——|————————–|

    | 通常(float16) | 約70秒 |

    | TensorRT最適化後 | 約28秒 |

    TensorRT化によって約2.5倍の高速化を確認できた。初回のエンジン変換に時間がかかるが、一度変換してしまえば同じエンジンを使い回せる。SuperモデルではDLAコア併用でさらに高速化可能。

    よくあるエラーと対処法

    「CUDA out of memory」が出る

    スワップの設定を再確認する。また enable_attention_slicing() に加えて以下も試す。

    
    pipe.enable_sequential_cpu_offload()
    

    torch2trtのビルドが失敗する

    CUDAのバージョンとPyTorchのバージョンが一致していない場合に起きやすい。nvcc --versiontorch.version.cuda が同じバージョンを示しているか確認する。TensorRTメモリ不足時はFP32レイヤー強制やopset17使用を検討。

    変換後のエンジンで型エラーが出る

    fp16_mode=True にしている場合、推論時の入力テンソルも .half() にする必要がある。

    まとめ

    Jetson Orin NanoでのStable Diffusion動作をまとめると次の通りだ。

  • 8GB Superモデルの使用とスワップ拡張が安定動作の前提条件になる
  • TensorRT化によって生成速度を約2.5倍に改善できる
  • エンジン変換には時間がかかるが、一度作成すれば使い回せる
  • 冷却対策を怠ると変換中にサーマルスロットリングが発生する
  • Jetson Orin NanoはRaspberry Pi 5などと比べてGPUを持っているのが最大の強みだ。画像生成AIのような重い処理でその差が明確に出る。エッジでの画像生成を試してみたい方はぜひ挑戦してほしい。

    次はこちら

    TensorRT最適化をさらに深く理解したい方、あるいはほかのAIモデルをJetson上で動かしたい方は以下の記事も参考にしてほしい。

  • Jetson Orin Nano TensorRT高速化チュートリアル
  • Jetson Orin NanoでYOLOv8をリアルタイム物体検出する方法
  • Jetson Orin Nano 熱対策・冷却方法まとめ
  • コメント

    タイトルとURLをコピーしました