メインコンテンツへスキップ
見出し画像

[Stable Diffusion] reForgeが遅くて悩んでた件 →2025/12/28修正されました!

    2025/12/25更新:原因コードの元となったComfyUIのコードについて追記
     reForgeのissueとして報告したことを追記
    2025/12/28更新:reForge開発元で修正され動作確認したことを追記
    2026/1/10更新:本件の対応で実装された --pin-shared-memory 関連コードのrevertについて追記


    「Stable Diffusion A1111系WebUIまとめ③ ~性能編~」を書こうと各ツールの性能測定をしていたのですが、reForgeが変に遅くて数日間悩んでいました。

    ようやく原因切り分けができたので解説します。
    特にStabilityMatrixでreForgeを使っている人は同じ問題が発生しているかもしれませんので確認してください。

    ※ 2025/12/28にreForge開発元で修正されこの記事の問題が解消したことを確認しました。

    概要と結論

    できるだけ簡単に概要と結論を先に書きます。

    reForgeはコマンドライン引数(webui-user.batのCOMMANDLINE_ARGSに記載)でVRAM管理の動作を設定することができます。

    --always-gpu
     Store and run everything (text encoders/CLIP models, etc... on the GPU).
    --always-high-vram
     By default models will be unloaded to CPU memory after being used. This option keeps them in GPU memory.
    --always-normal-vram
     Used to force normal vram use if lowvram gets automatically enabled.
    --always-low-vram
     Split the unet in parts to use less vram.
    --always-no-vram
     When lowvram isn't enough.

    https://github.com/Panchovix/stable-diffusion-webui-reForgeからVRAM関連で主なものを抜粋

    これらの引数を付けない場合は "--always-normal-vram" を付けた場合と同じ動作になります(起動時に "Set vram state to: NORMAL_VRAM” とメッセージ出力されます)。

    他に "--pin-shared-memory" という引数があり、こちらはモデルをVRAMからメインメモリへオフロードする際の高速化処理方式です。
    これを付けていないと起動時に "Hint: your device supports --pin-shared-memory for speed improvements if having 16GB or more VRAM. It may cause issues with 12GB VRAM or less." といかにも「付けると速くなるよ」というメッセージ出力されるアレです。

    この "--pin-shared-memory" を付けた場合の挙動が、ForgeやForge Classic、そしてreForgeの2025年3月11日の大規模アップデート前の保存ブランチであるmain-old(以後reForge-old)と異なる部分があり、大きな性能低下を引き起こすことがあるというのがこの記事のポイントです。

    現在のreForge(以後reForge-main)では "--pin-shared-memory" を付けた場合、"--always-gpu" か "--always-high-vram" を付けていないと、画像生成後にモデルをVRAMから毎回オフロードするようになっています。
    そのため同じモデルを使う場合でも生成するたびにモデルを再ロードするので、その分だけ時間がかかってしまいます。

    他のForge系、reForge-oldではそのようなことはありません(EasyReforgeはreForge-oldと同等です)。

    reForge-mainの毎回のモデルオフロードを回避する方法は大きく2つあります。
    ・対策1:"--pin-shared-memory" を使用しない
    ・対策2:"--pin-shared-memory" を使用する場合は "--always-gpu" か "--always-high-vram" を併用する
    基本的には対策1で、VRAMに余裕がある場合は対策2でもよいでしょう。

    なお、Stability Matrixの最新バージョン(v2.15.4)でreForge-mainをインストールすると "--pin-shared-memory" が有効になった状態に設定される(昔のバージョンでは無効だったはず)ため、そのままだとこの問題が発生します。
    Stability MatrixでreForge-mainを使ってる人は要確認です。

    問題事象の確認

    VRAM関連引数を付けずに "--pin-shared-memory" を付けた際のreForge-main(2025/12/18版)とreForge-oldの挙動について、モデル、プロンプト、その他の設定を変更せずに2回連続で画像生成した際の処理速度とVRAM使用量がどのように違うか示します。

    まず処理速度についてはコンソールメッセージで確認できます。

    <<reForge-mainのコンソールメッセージ>>
    
    ※1回目の生成
    100%|██████████| 28/28 [00:02<00:00,  9.50it/s]
    Total progress: 100%|██████████| 28/28 [00:04<00:00,  6.59it/s]s]
    
    ※2回目の生成
    100%|██████████| 28/28 [00:02<00:00, 10.24it/s]
    Total progress: 100%|██████████| 28/28 [00:04<00:00,  6.99it/s]s]
    <<reForge-oldのコンソールメッセージ>>
    
    ※1回目の生成
    No new models to load
    No new models to load
    Begin to load 1 model
    [Memory Management] Current Free GPU Memory (MB) = 28927.73
    [Memory Management] Model Memory (MB) = 4897.09
    [Memory Management] Minimal Inference Memory (MB) = 1024.00
    [Memory Management] Estimated Remaining GPU Memory (MB) = 23006.64
    Moving model(s) has taken 0.88 seconds
    100%|██████████| 28/28 [00:02<00:00,  9.55it/s]
    Begin to load 1 model
    [Memory Management] Current Free GPU Memory (MB) = 24051.16
    [Memory Management] Model Memory (MB) = 159.56
    [Memory Management] Minimal Inference Memory (MB) = 1024.00
    [Memory Management] Estimated Remaining GPU Memory (MB) = 22867.60
    Moving model(s) has taken 0.06 seconds
    Total progress: 100%|██████████| 28/28 [00:03<00:00,  8.82it/s]s]
    
    ※2回目の生成
    Begin to load 1 model
    Reuse 1 loaded models
    [Memory Management] Current Free GPU Memory (MB) = 23889.60
    [Memory Management] Model Memory (MB) = 0.00
    [Memory Management] Minimal Inference Memory (MB) = 1024.00
    [Memory Management] Estimated Remaining GPU Memory (MB) = 22865.60
    Moving model(s) has taken 0.03 seconds
    100%|██████████| 28/28 [00:02<00:00,  9.95it/s]
    No new models to load
    Total progress: 100%|██████████| 28/28 [00:03<00:00,  9.14it/s]s]

    生成回数生成速度total速度reForge-main1回目9.50it/s6.59it/s2回目10.24it/s6.99it/sreForge-old1回目9.55it/s8.82it/s2回目9.95it/s9.14it/s\begin{array} {l|c|c|c} & \text{生成回数} & \text{生成速度} & \text{total速度} \\ \hline \text{reForge-main} & \text{1回目} & \text{9.50it/s} & \text{6.59it/s}\\ \hline & \text{2回目} & \text{10.24it/s} & \text{6.99it/s}\\ \hline \text{reForge-old} & \text{1回目} & \text{9.55it/s} & \text{8.82it/s}\\ \hline & \text{2回目} & \text{9.95it/s} & \text{9.14it/s}\\ \end{array}

    そもそもメッセージ量が全然違いますが、生成(サンプリング)の速度はいずれも同等であるのに対して、totalの速度はreForge-mainがかなり低速であることが分かります。
    またreForge-oldでは2回目の生成で "Reuse 1 loaded models" と表示されており、VRAMに保持されたモデルを再利用していることが分かります。

    次にVRAM使用量についてはタスクマネージャーのGPU項目で確認できます。

    画像
    reForge-mainのGPUリソース情報
    画像
    reForge-oldのGPUリソース情報

    reForge-mainは生成のたびにVRAM(専用GPUメモリ)からモデルをオフロードしていますが、reForge-oldは保持していることが分かります。

    対策設定後の確認

    reForge-mainで対策1、対策2それぞれを設定した場合の効果を示します。

    <<reForge-main(対策1)のコンソールメッセージ>>
    
    ※1回目の生成
    100%|██████████| 28/28 [00:02<00:00,  9.53it/s]
    Total progress: 100%|██████████| 28/28 [00:03<00:00,  8.92it/s]s]
    
    ※2回目の生成
    100%|██████████| 28/28 [00:02<00:00, 10.17it/s]
    Total progress: 100%|██████████| 28/28 [00:03<00:00,  9.11it/s]s]
    <<reForge-main(対策2)のコンソールメッセージ>>
    
    ※1回目の生成
    100%|██████████| 28/28 [00:02<00:00,  9.52it/s]
    Total progress: 100%|██████████| 28/28 [00:03<00:00,  8.84it/s]s]
    
    ※2回目の生成
    100%|██████████| 28/28 [00:02<00:00,  9.81it/s]
    Total progress: 100%|██████████| 28/28 [00:03<00:00,  8.88it/s]s]

    生成回数生成速度total速度対策11回目9.53it/s8.92it/s2回目10.17it/s9.11it/s対策21回目9.52it/s8.84it/s2回目9.81it/s8.88it/s\begin{array} {l|c|c|c} & \text{生成回数} & \text{生成速度} & \text{total速度} \\ \hline \text{対策1} & \text{1回目} & \text{9.53it/s} & \text{8.92it/s}\\ \hline & \text{2回目} & \text{10.17it/s} & \text{9.11it/s}\\ \hline \text{対策2} & \text{1回目} & \text{9.52it/s} & \text{8.84it/s}\\ \hline & \text{2回目} & \text{9.81it/s} & \text{8.88it/s}\\ \end{array}

    いずれもtotalの速度がreForge-oldと同等になりました。

    画像
    reForge-main(対策1)のGPUリソース情報
    画像
    reForge-main(対策2)のGPUリソース情報

    いずれも生成後にモデルをVRAMからオフロードしなくなりました。

    原因になっているコード

    ここから先は細かい話であり、主に自分用メモなので興味が無ければ飛ばしてください。

    VRAMオフロード処理はldm_patched/modules/model_management.pyというモジュールに書かれており、reForge-mainとreForge-oldのコードを比較して、"--pin-shared-memory" が指定されていると常にモデルをオフロードするよう変更したコミットを確認することができました。

    <<変更前>>
    
    (432行目)
    def free_memory(memory_required, device, keep_loaded=[]):
        offload_everything = ALWAYS_VRAM_OFFLOAD or vram_state == VRAMState.NO_VRAM
    
    (446行目) ※ def free_memory(memory_required, device, keep_loaded=[]): 内
            if not offload_everything:
                if get_free_memory(device) > memory_required:
                    break
            m = current_loaded_models[i]
            m.model_unload()
            unloaded_models.append(m)
    <<変更後>>
    
    (280行目)
    DISABLE_SMART_MEMORY = args.pin_shared_memory
    
    if DISABLE_SMART_MEMORY:
        logging.info("Disabling smart memory management")
    
    (中略)
    
    (449行目) ※ def free_memory(memory_required, device, keep_loaded=[]): 内
            if not DISABLE_SMART_MEMORY:
                free_mem = get_free_memory(device)
                if free_mem > memory_required:
                    break
                memory_to_free = memory_required - free_mem
            logging.debug(f"Unloading {current_loaded_models[i].model.model.__class__.__name__}")
            if current_loaded_models[i].model_unload(memory_to_free):
                unloaded_model.append(i)

    VRAMオフロードの条件が、変更前は "--always-offload-from-vram" または "--always-no-vram" という常にVRAMからオフロードする引数を付けた場合だったのに対し、変更後は "--pin-shared-memory" になっています。

    このコードはComfyUIのコードから取り込んだとのことなので、ComfyUIのコードを探すと同名のモジュールcomfy/model_management.pyと対応するコードを発見しました。

    (420行目)
    DISABLE_SMART_MEMORY = args.disable_smart_memory
    
    if DISABLE_SMART_MEMORY:
        logging.info("Disabling smart memory management")
    
    (中略)
    
    (600行目) ※def free_memory(memory_required, device, keep_loaded=[]): 内
            if not DISABLE_SMART_MEMORY:
                free_mem = get_free_memory(device)
                if free_mem > memory_required:
                    break
                memory_to_free = memory_required - free_mem
            logging.debug(f"Unloading {current_loaded_models[i].model.model.__class__.__name__}")
            if current_loaded_models[i].model_unload(memory_to_free):
                unloaded_model.append(i)

    DISABLE_SMART_MEMORYにもとづいてオフロードするのは同じですが、DISABLE_SMART_MEMORYが参照する引数がまったく違いますね。
    ComfyUIで参照しているのは "--disable-smart-memory" という引数で、"Force ComfyUI to aggressively offload to regular ram instead of keeping models in vram when it can."(可能な場合は、モデルを VRAM に保持するのではなく、ComfyUI が通常の RAM に積極的にオフロードするように強制します。)と説明されているものです。


    2025/12/25追記
    reForgeのバグだと思いますのでissueとして報告しておきました。
    2025/12/28追記
    上のissueでのやりとりのとおり修正され、"--pin-shared-memory" を指定しても生成後にモデルがVRAMからオフロードされないことを確認しました。
    2026/1/10追記
    本件の対応で実装された "--pin-shared-memory" 関連コードがrevert(取消)されました。本件の修正において誤った実装が削除され、本来の動作が実装されたのですがメモリリークが発生しているようです。revertにより現在 ”--pin-shared-memory" は設定しても何も機能しません(当然本記事の問題も発生しません)。

    まとめ

    reForge-mainで "--pin-shared-memory" を付けると、"--always-gpu" か "--always-high-vram" を併用しない限りモデルのオフロード動作によって生成速度が低下する問題と対策について解説しました。

    特に最近StabilityMatrixでreForge-mainをインストールした人は同じ問題が発生しているかもしれませんので確認することをおススメします。

    このような感じで、あまり体系的に整理や理解されていない技術的な内容を分かりやすく無料で解説しています。「スキ」「フォロー」「チップ」で応援よろしくお願いします。

    あなたへのおすすめ