西川和久の不定期コラム

BeelinkのミニPC「GTi13 Ultra」を、WindowsとDockerで環境構築して最後デュアルGPU化!?

 前回、ドッキングステーションを使い、dGPUをPCIe x8接続できるBeelink製のミニPC「GTi13 Ultra」をご紹介した。今回はこれを使ってAI PC化してみたい。

メモリを64GBへ、ストレージ2TB追加

 「AI PC」と言っても人によって用途はさまざま。筆者はご存じのように画像(たまに動画)生成とLLMが主な用途となるだろうか。

 この場合、各モデルのファイルサイズが巨大(数十GBなんて普通)なのでストレージはたっぷり欲しい。メインメモリ(RAM)やビデオメモリ(VRAM)も同様。ただ一般的なPCだとRAMは32GB×2の64GBまでがお手頃。それ以上だといろいろコストアップする。VRAMは選ぶdGPU次第。増えると価格が……となる。今回追加で用意したのは以下の通り。

今回用意したもの。SO-DIMM 32GB×2、M.2 2280 SSD 2TB。8ピン二股ケーブル(2種類)
メモリを32GB×2の64GBへ交換、M.2 2280 2TB SSD追加
メモリ無事認識
SSD無事認識

 SO-DIMM 32GB×2、M.2 2280 SSD 2TB。そしてGPU補助電源の8ピンを二股にするケーブルと、GPU補助電源の8ピン×2を12VHPWRにするケーブル。

 メモリとストレージは、このBeelink「GTi13 Ultra」の場合、交換が結構面倒なので先に済ます。鬼門のスピーカーからも無事音が出るのを確認。

 dGPUの交換は最後にして、テストで付けたGeForce RTX 4060 Ti(16GB)のままで環境構築を行ない、仕上げにより強力なdGPUへ入れ替えるため変換ケーブルを……となる。

必要なソフトウェアのインストール

 本来AI環境はUbuntuの方が有利なのだが(Windowsだとpythonのライブラリでないものや、入れるのが面倒なものが結構ある)、せっかくWindows 11 Pro(24H2)が入っているのでこれをそのまま使い、AI環境はDocker上で動かすことにした。AI関連の設定を行なう前にまずやったことは以下の通り。

  1. IPアドレス固定
  2. RemoteDesktop
  3. OpenSSHサーバー
  4. Docker Desktop
  5. Git for Windows
  6. nano for Windows
  7. Mini Conda
OpenSSHサーバーのインストール
Docker Desktopインストール中にWSL2を使うにチェックが入っている

 1から3まではWindows標準搭載の機能。4から7もpythonの環境としては一般的なので特に説明の必要はないだろう。主にサーバー的に扱えるようにするものだ。

 WSLに関してはDocker Desktopをインストールすれば自動的に設定される(当初は違ったような……)。今回はメインのAI PCに合わせてUbuntu 22.04 LTSをチョイス。nanoはCLI用の簡単なエディタだ。CLIで操作中、GUIからnotepadを開くのが面倒な時、ちょっとした書込みはこれを使うことが多い。

 次にAI関連は増設した2TB(D:ドライブ/NTFS)の方へ入れる。モデルの多くは生成
AI画像と動画用。フォーマット後容量は約1.9TBほどあるのだが、メインのAI PCから全部コピーしたら残200GBになってしまった(笑)。

Windows + Docker失敗/リカバリ編

 とりあえず適当にComfyUI用のDockerfileを作り動かしたところ、動くのは動くのだがcheckpoint(モデル)の読み込みが激遅く分単位でかかる。読み込んだ後は普通の速度なので、このファイルアクセスだけ何とかしたいのだが、調べると……。

“NTFS/EXT4変換に時間がかかり遅い”

とあり、このままではどうにもならないようだ。手としては、

“SSDをEXT4でフォーマット、それをWSL側でマウントする”

となる。せっかく大量のモデルファイルをコピーしたのにまたフォーマットして入れ直しだ。Windowsの標準機能ではEXT4にフォーマットできないため、WSLのUbuntu上で処理を行なう。手順は以下の通り。

1. PowerShellを使いデバイスIDの確認
PS C:\Users\knishika> GET-CimInstance -query "SELECT * from Win32_DiskDrive"

DeviceID           Caption          Partitions Size          Model
--------           -------          ---------- ----          -----
\\.\PHYSICALDRIVE0 HP SSD FX700 2TB 0          2048407280640 HP SSD FX700 2TB
\\.\PHYSICALDRIVE1 CT1000P3PSSD8    3          1000202273280 CT1000P3PSSD8
2. WSLに接続(PowerShell管理者権限)
PS C:\Users\knishika> wsl --mount \\.\PHYSICALDRIVE0 --bare
3. WSLのUbuntu上でEXT4にフォーマット
$ lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
loop0    7:0    0 510.9M  1 loop /mnt/wsl/docker-desktop/cli-tools
loop1    7:1    0 647.7M  1 loop
sda      8:0    0 388.4M  1 disk
sdb      8:16   0     8G  0 disk [SWAP]
sdc      8:32   0     1T  0 disk /mnt/wsl/docker-desktop/docker-desktop-user-distro
sdd      8:48   0     1T  0 disk
sde      8:64   0     1T  0 disk /mnt/wslg/distro
                                 /
sdf      8:80   0   1.9T  0 disk
└─sdf1   8:81   0    16M  0 part
※ sdfが目的のdisk

$ sudo apt install e2fsprogs
$ sudo mkfs.ext4 /dev/sdf
mke2fs 1.46.5 (30-Dec-2021)
Found a gpt partition table in /dev/sdf
Proceed anyway? (y,N) y
Creating filesystem with 500099670 4k blocks and 125026304 inodes
Filesystem UUID: a408588a-1025-426a-80aa-247b65a8b214
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
        102400000, 214990848

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done
4. マウントする
$ sudo mkdir /mnt/AI
$ sudo mount /dev/sdf /mnt/AI

1と2がWSL固有で、後はUbuntuでは普通の手法。特に難しいことはしていない。なおWindowsからこのEXT4のドライブにアクセス(読み書き可能)する方法があり、

\\wsl.localhost\Ubuntu-22.04\mnt\AI

とすれば良い。とりあえずここまでできたら後は大量のモデルファイルをコピー。一晩かかるので、開始後放置しておく。これでファイルアクセスが遅い=失敗編はリカバリした。

WindowsからUbuntuにアクセス可能

Windows+Docker+EXT4成功編

 明けてモデルコピー終了したのを確認後、いよいよ環境構築となる。また今回のケースだと、C:ドライブはWindows込みの1TB、EXT4ドライブは2TB。LLM用のLM Studioは、特にpythonの環境縛りなどがないため、C:ドライブ側に入れ、画像/動画生成系のみDockerで対応する。相互でモデルファイルをアクセスすることもなく、これは問題ないだろう。

 次にWSLは搭載メモリの半分を割り当てるのがデフォルトらしく64GBにした意味がない。増やす方法はホームフォルダ直下に .wslconfig ファイルを作り

[wsl2]
memory=50GB
swap=32GB
processors=8
※ 後にmemory=54GBへ変更

とする。その後、

PS C:\Users\knishika> wsl --shutdown
PS C:\Users\knishika> wsl
PS C:\Users\knishika> wsl --mount \\.\PHYSICALDRIVE0 --bare
※ 最後は管理者としてPowerSellを起動

これでOKだ。確認は、

$ free -h
               total        used        free      shared  buff/cache   available
Mem:            49Gi        21Gi        24Gi       190Mi       3.2Gi        27Gi
Swap:           32Gi       1.1Gi        30Gi

メモリが増えているのが分かる。

 Windows側でインストールしたDockerをUbuntuでも使えるよう、Docker Desktopの設定→Resources→WSL integrationでUbuntu-22.04をオン。これで連携が可能となる。

DockerのUbuntu連携。Docker Desktopの設定→Resources→WSL integration で Ubuntu-22.04をオン

 次に通常Ubuntu版Dockerはrootを使うため、sudo docker xxxxxとなるのだが、sudoなしでdockerを起動するには

$ sudo usermod -aG docker $USER

とすれば良い。仕上げは、

$ sudo apt install net-tools
$ sudo apt install openssh-server
$ sudo systemctl enable ssh

これによりWindowsのCMD / PowerShellからUbuntuにssh接続可能になる(ifconfigでUbuntu側のIPアドレスを確認)。Windows上だけで操作するなら不要であるが、別のPC→sshでこのPCにログイン→から再度sshでUbuntuにログイン……と、ほかのPCからこのUbuntuを操作するのに便利だ。

macOSのTerminalからWindowsのUbuntuへログイン

 ComfyUIのインストールは、先にUbuntu側の/mnt/AIで

$ git clone https://github.com/comfyanonymous/ComfyUI.git
$ cd ComfyUI
$ cd custom_nodes
$ git clone https://github.com/ltdrdata/ComfyUI-Manager.git
$ cd ..
$ cd ..

としておき、同一階層上に(つまり/mnt/AI)に docker-compose_comfyui.ymlを作る(docker-compose.ymlにしなかったのは、以降、この階層にいろいろ入る予定のため)。

services:
  comfyui:
    image: nvcr.io/nvidia/pytorch:25.01-py3
    volumes:
      - /mnt/AI/ComfyUI:/ComfyUI/
command:
    - /bin/bash
    - -c
    - |
      apt update
  python -m pip install --upgrade pip
      apt install -y git python3-pip libgl1-mesa-dev libglib2.0-0
      pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu128
      cd /ComfyUI/
      pip install -r requirements.txt
      python main.py --listen --fast
    deploy:
      resources:
        reservations:
          devices:
          - driver: nvidia
            capabilities: [gpu]
    ports:
      - "8188:8188"

 nvcr.io/nvidia/pytorch:25.01-py3は、CUDAなどNVIDIAのフレームワークが入ったイメージとなる。実はこの25.01-py3/whl/nightly/cu128は、GeForce RTX 5090対応のもので、GeForce RTX40系は下位互換で動くだろうとテスト的に使ってみた。前者を24.12-py3、後者を/whl/cu126とすれば、Python 3.12、CUDA 12.6、PyTorch cu126が入る。

 この点はDockerの便利なところで、Ubuntu本体にあるバージョンのCUDAをapt installしてしまうと、CUDAを使うすべてのアプリでCUDAやPyTorchのバージョンを合わせる必要があり大騒動となる。ところがDockerだとコンテナ単位で切り替えが可能。ディスプレイドライバだけ入れておけば良く、使い勝手が非常に良い。

 起動は、WSL / Ubuntuのコンソールから

$ docker-compose -f docker-compose_comfyui.yml up

でOK。http://localhost:8188やhttp://[PCのIPアドレス]:8188で、ComfyUIが起動する。初回はいろいろライブラリなどをインストールするので時間がかかるものの、docker-compose downしない限り、2回目以降はそこそこ速く起動する。

docker-composeを使ってWSLのUbuntu上でComfyUIを起動

 次はSwarmUI。生成AI画像系のWebUIはAUTOMATIC1111、Forge、Fooocusなどいろいろあったが、FLUX.1登場以降、アーキテクチャが異なるモデルが乱立しており、それらの対応にまったく追いついていないのが現状だ。唯一、ComfyUIはノードの組み合わせと言う設計思想から対応できている。

 その中で、何とか多くを取り込みつつ、使い勝手も良いのがこのSwarmUI。筆者は以前からロジック検証はComfyUI、普通に画像生成はSwarmUI(バックエンドはComfyUI、フロントエンドは.NET)を使っている。と言うことでこれは是非入れたいWebUIとなる。

 こちらは同じく/mnt/AI下で

$ git clone https://github.com/mcmonkeyprojects/SwarmUI.git

とし、SwarmUIフォルダの中にgo.shというDocker起動用のスクリプトと、ComfyModelsフォルダを作ってある。このComfyModelsフォルダは、コンテナ内に/mnt/AI/ComfyUI/modelsをマウントして、モデルファイルを共通で使うための仕掛けだ。

SETUSER=""
POSTARG="$@"
docker run -it \
    --rm \
    $SETUSER \
    --name swarmui \
    --mount source=swarmbackend,target=/SwarmUI/dlbackend \
    --mount source=swarmdata,target=/SwarmUI/Data \
    --mount source=swarmdlnodes,target=/SwarmUI/src/BuiltinExtensions/ComfyUIBackend/DLNodes \
    -v "$PWD/Models:/SwarmUI/Models" \
    -v "$PWD/Output:/SwarmUI/Output" \
    -v "/mnt/AI/ComfyUI/models:/SwarmUI/ComfyModels" \
    -v "$PWD/src/BuiltinExtensions/ComfyUIBackend/CustomWorkflows:/SwarmUI/src/BuiltinExtensions/ComfyUIBackend/CustomWorkflows" \
    --gpus=all -p 7801:7801 -p 7821:7821 swarmui $POSTARG

 初回起動時はhttp://[PCのIPアドレス]:7801でWebUIを使ったインストーラが起動、終了後、SwarmUIが起動する。ポート7821は、バックエンドで作動するComfyUIを直接操作する用。

dockerを使ってWSLのUbuntu上でSwarmUIを起動

 起動後、Server→Server Configurationで、各モデルのpathを設定/保存する。たとえば、SDModelFolder: /SwarmUI/ComfyModels/checkpointsといった感じで、/SwarmUI/ComfyModelsの後ろは、ComfyUI/modelsの該当するフォルダ名となる。

LM Studioで話題のDeepSeekを使用中(正確にはcyberagent-DeepSeek-R1-Distill-Qwen-32B-Japanese-GGUF)

 LLM用のLM Studioは、普通にWindows側(C:ドライブ)へインストールする。これで環境は整った!

仕上げは!?GeForce RTX 4090(24GB)+eGPU(USB4)接続GeForce RTX 4060 Ti(16GB)でデュアルGPU環境へ!

 この状態でしばらく遊んでいたが、GeForce RTX 4060 Ti(16GB)は、VRAM容量はともかくとして、生成時間が普段使っているGeForce RTX 4090(24GB)の4倍ほどかかる(例: FLUX.1 [dev] 25steps + Tea Cache/前段のみを使い5.71秒 vs 24.43秒)。やはり……(笑)。

 ということで、GeForce RTX 4090(24GB)へ入れ替えることにした。「へ?600W電源とは言え8ピン×2で大丈夫なの?」と多くの人は思うだろが、メーカーに確認したところGeForce RTX 4090(24GB)はOKとの返事。

 GeForce RTX 4090(24GB)のTDPは450W。つまり8ピン×3でピーク時を除けばこと足りる。ドッキングステーションの3スロット対応もこのためだろう。ただしGeForce RTX 5090(32GB)はダメだったとのこと(原因不明)。ここで冒頭に書いた変換ケーブルの登場となる。使ったのは8ピン×2を12VHPWRにするケーブル。もう一方の普通の8ピンから二股ケーブルはもしもの時の予備とした。

GTi13 UltraとGeForce RTX 4090(24GB)の合体(1/4)。大きいので結構はみ出している
GTi13 UltraとGeForce RTX 4090(24GB)の合体(2/4)。電源ケーブル周辺。この後、バンドでまとめた
GTi13 UltraとGeForce RTX 4090(24GB)の合体(3/4)。3スロット幅がしっかり収まっている
GTi13 UltraとGeForce RTX 4090(24GB)の合体(4/4)。裏から見た方がカッコいい(笑)

 OSがGeForce RTX 4090(24GB)を認識しているのを確認後、3DMark / Time Spy完走!スコアは27,598。GeForce RTX 4060 Ti(16GB)が13,284だったので約2倍速となる。

無事GeForce RTX 4090(24GB)を認識
3DMark / Time Spy。完走!スコアは27,598

 次に先の生成AI画像のPromptやパラメータをまったく同じにして6.53秒。もともと5.71秒だったので0.82秒遅くなっている。これはDockerのオーバーヘッドか?PCIe x16とPCIe x8との差なのか不明。ただ目くじら立てるほどでもない。

 ここまで動いてふっと思ったのは、「USB4があるからeGPU Box付くのでは?」だ。試しに外したGeForce RTX 4060 Ti(16GB)を接続したところOK。なんととGeForce RTX 4090(24GB)とGeForce RTX 4060 Ti(16GB)のデュアルGPU環境となった。

 ただし、eGPUはThunderbolt 3/40Gbpsなので、OCulink/63Gbpsより遅く、GPUの性能はフルに出ない。それでも良ければ……という感じだ。

USB4でGeForce RTX 4060 Ti(16GB)を加えデュアルGPU環境に!
後ろにあるボックスが以前使っていたThunderbolt3(USB4)接続のeGPU Box + GeForce RTX 4060 Ti(16GB)

 生成AI画像(動画)時は両方足してVRAM 40GBにはならないが、たとえばLLMはGeForce RTX 4060 Ti(16GB)、生成AI画像はGeForce RTX 4090(24GB)と、処理に応じて使い分けが可能となる。

 またsd-scripts(学習ツール)やLM Studioでは、2つのGPUを合体させVRAMを40GB(24+16GB)として扱うことができる。処理速度は遅い方のGPUになってしまうのが残念なところ。とは言え、LLMはVRAMに乗らないとそもそも動かないので、合算できるだけでもありがたい。

LM Studioでは2つのGPUを合体させVRAMを40GB(24+16GB)として扱うことができる

 いかがだろうか?ちょっとやり過ぎ感もあるのだが(笑)、PC 1台でここまでできればいろいろ楽しめる。「GTi13 Ultra」の次バージョンは、是非OCuLinkにも対応してほしいところか!?


デュアルGPU AI PC完成!

 以上のようにBeelink「GTi13 Ultra」+「Multi-Functional EX Docking Station」を使い、dGPUとしてGeForce RTX 4090(24GB)を接続(PCIe x8)。続いてUSB4を使いeGPU Box + GeForce RTX 4060 Ti(16GB)も追加。デュアルGPUのAI PCが完成した!この原稿を書きながらいろいろ試しているがなかなか快適!

 さて、元々GeForce RTX 4090(24GB)が付いていたUbuntu/AI PCは、現在、GPUがなく、単なるPCになっている。Core i7-12650H、メモリ64GB(ただしDDR4)、SSD 512GB+1GB+2TB、電源1,000WのPCを余らすのはもったいない。これに何を入れるのか!?はご想像通り(笑)。入手次第、記事にしてみたい。お楽しみに♪