Hyper-VでGPU(GPU-PV)を利用する方法 (Ubuntu編)

## `Windows Server 2025`にて正式サポート

[https://techcommunity.microsoft.com/t5/windows-server-news-and-best/the-future-of-windows-server-hyper-v-is-bright/ba-p/4074940](https://techcommunity.microsoft.com/t5/windows-server-news-and-best/the-future-of-windows-server-hyper-v-is-bright/ba-p/4074940)

`Windows Server 2025`にて、`GPU-P`は正式にサポートされるようになるようです。

こちらで紹介している有効化手順は正式サポート以前のものになります。

正式な手順は異なる可能性があります。

正式な手順は公式のドキュメントを確認してください。

ただし、こちらの手順では、公式的にはサポートされないハードウェア構成でも使用可能かもしれません。

## はじめに

この記事の`Windows`版は[ここ](https://qiita.com/Hyper-W/items/e189790fd4534d9d51ad)です。

`Hyper-V`を利用する`WSL2`では、`GPU-PV`(`Para Virtualization`)と呼ばれる技術を利用することで、`Windows 10 (21H1)`以降`Nvidia`製`GPU`を用いる`CUDA`プログラミングが、`WSL2`上やそれをバックエンドとして利用する`Docker`で可能になりました。

また、最近では、[`Azure Stack HCI`](https://learn.microsoft.com/ja-jp/azure-stack/hci/manage/partition-gpu)でも、サポートされている`GPU`は限られますが、`Linux`上での`GPU-PV`が利用可能なようです(この記事の手順を利用すれば非対応`GPU`でも利用可能な可能性があります)。

既に利用されているということは、`Windows`に実装されているということです。

実際に、`Powershell`で`Hyper-V`に関するコマンドを調べると、下記のようなコマンドで、

```Powershell
Get-Command -module Hyper-V
```

下記のような結果が得られます。

```Powershell
CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
                (前略)
Cmdlet          Add-VMGpuPartitionAdapter                          2.0.0.0    Hyper-V
                (中略)
Cmdlet          Get-VMGpuPartitionAdapter                          2.0.0.0    Hyper-V
                (中略)
Cmdlet          Remove-VMGpuPartitionAdapter                       2.0.0.0    Hyper-V
                (中略)
Cmdlet          Set-VMGpuPartitionAdapter                          2.0.0.0    Hyper-V
                (後略)
```

上記のように既に実装されています。

`Get-Help`コマンドで調べると構文は出てきますが、説明はまだ公式サポートされていないので、出てきません(`Powershell 7`以降で実行すると更に詳しい構文が出てきます)。

この技術が、通常の`Windows`(サーバー含む)では、サポートされていませんが、`Windows`仮想マシンでは利用可能であることは、[既に記事](https://qiita.com/Hyper-W/items/e189790fd4534d9d51ad)にした通りです。

`WSL2`において、既に利用されているということは、公開されている`WSL2`専用にカスタムしたカーネルをベースに`Hyper-V`でも利用できるように変更すれば、`Hyper-V`上の`Linux`でも利用可能であるということです。

今回は、[`Hyper-V`の`Linux`でも`GPU-PV`を利用可能にするカスタムカーネルの`Ubuntu`向けパッケージ](https://github.com/brokeDude2901/dxgkrnl_ubuntu)を公開されている方が居たので、このカーネルを利用して、`Hyper-V`上の`Kubuntu 22.04 LTS`で、`GPU-PV`を利用します。

カスタムカーネルは、`Ubuntu 20.04`及び`Ubuntu 22.04`でテストされているようですが、他の`Ubuntu`のバージョンや`Ubuntu`ベースのディストリビューション、`Debian`ベースのディストリビューションでも動作する可能性があります。

この記事では、`Kubuntu 22.04 LTS`環境で、仮想`GPU`の割り当てから、`GPU`ドライバーの適用を行う手順を紹介します。

仮想`GPU`の割り当て、親マシン上にある`GPU`ドライバーの保存場所の確認については、`Windows`版の記事と同様です。

## 目次

- [`Windows Server 2025`にて正式サポート](#windows-server-2025にて正式サポート)
- [はじめに](#はじめに)
- [目次](#目次)
- [動作確認環境](#動作確認環境)
- [仮想マシンで、仮想`GPU`を利用できるようにする](#仮想マシンで仮想gpuを利用できるようにする)
  - [チェックポイントの無効化](#チェックポイントの無効化)
  - [仮想`GPU`の割り当て方法](#仮想gpuの割り当て方法)
    - [`GPU Partition Adapter`の割り当て](#gpu-partition-adapterの割り当て)
      - [マルチ`GPU`環境での割り当てについて](#マルチgpu環境での割り当てについて)
    - [仮想`GPU`のリソース設定](#仮想gpuのリソース設定)
  - [仮想マシンに準仮想`GPU`のドライバーを追加する方法](#仮想マシンに準仮想gpuのドライバーを追加する方法)
    - [親マシン上にある`GPU`ドライバーの保存場所の確認](#親マシン上にあるgpuドライバーの保存場所の確認)
    - [仮想マシンへのドライバーコピー](#仮想マシンへのドライバーコピー)
  - [カスタムカーネルのインストール](#カスタムカーネルのインストール)
  - [`Grub`メニューからカスタムカーネルを選択できるようにする](#grubメニューからカスタムカーネルを選択できるようにする)
  - [カスタムカーネルを選択して起動](#カスタムカーネルを選択して起動)
- [(`Nvidia`製`GPU`限定) `nvidia-smi`コマンドによる仮想`GPU`の確認](#nvidia製gpu限定-nvidia-smiコマンドによる仮想gpuの確認)
- [(`Nvidia`製`GPU`限定) Dockerで仮想`GPU`を利用する](#nvidia製gpu限定-dockerで仮想gpuを利用する)
  - [`Docker`のインストール](#dockerのインストール)
  - [`NVIDIA Container Toolkit`のインストール](#nvidia-container-toolkitのインストール)
  - [`Docker`コンテナ内で`nvidia-smi`を実行](#dockerコンテナ内でnvidia-smiを実行)
  - [`Hyper-V`仮想マシン上の`Ubuntu`上の`Docker`で`Stable Diffusion WebUI(AUTOMATIC1111)`を動かす](#hyper-v仮想マシン上のubuntu上のdockerでstable-diffusion-webuiautomatic1111を動かす)
- [GPU Partition Adapterの削除](#gpu-partition-adapterの削除)

## 動作確認環境

- 親マシン

```yml
OS: Windows 11
Version: 22H2
CPU: Intel Core i9 13900K(24C32T)
MEM: DDR5 128GB(4800MHz 32GB ×4)
GPU: Nvidia Geforce RTX 3080
```

- 子マシン

```yml
OS: Kubuntu 22.04.1 LTS
vCPU: 8C
MEM: 16GB
```

子マシンについては、カスタムカーネルを動作させるために、セキュアブートを無効化する必要があります。

`Ubuntu`は、`Hyper-V`のセキュアブートテンプレートで、`Microsoft UEFI`証明機関を選択している場合、利用可能ですが、カスタムカーネルを利用している場合は、**完全に無効にする必要があります。**

クイック作成ギャラリー等で作成した仮想マシンの場合は、意図せずに有効化されている可能性があるので、特に**無効になっていること**を確認して下さい。

## 仮想マシンで、仮想`GPU`を利用できるようにする

**注意**
**この機能は、公式にサポートされていない方法です。なにか問題が起きても自己責任です。**

### チェックポイントの無効化

まず、チェックポイントを適用・削除する必要があります。

これは、`GPU-PV`ではチェックポイントがサポートされておらず、有効化するためにはチェックポイントを無効化する必要があるためです。

そのため、自動チェックポイントを使っている場合は無効に、チェックポイントが既に存在する場合は、チェックポイントの削除または適用を、チェックポイントを利用しないことが必要です。

### 仮想`GPU`の割り当て方法

この項目での設定は、シングル`GPU`環境の場合、[この`bat`ファイル](https://github.com/Hyper-W/Hyper-V_GPU-PV-Single/blob/Qiita-GPU-PV/Hyper-V_GPU-PV-Single.bat)により一括実行可能です。

この`bat`ファイルはダブルクリックで、実行すると`UAC`で管理者権限に昇格し、仮想マシン名を聞いてくるので、設定したい仮想マシンの名前をシングルクォート(`'`)で囲み指定すると、一括で実行されます。

#### `GPU Partition Adapter`の割り当て

まずは、先程の`GPU Partitioning`関連のコマンドを利用して仮想マシンに`GPU Partition Adapter`を仮想マシンに割り当て、リソースの設定などを行います。

`Powershell`を**管理者権限**で実行して、下記コマンドを実行します。

まずは、仮想マシンに`GPU Partition Adapter`を割り当てます。

下記コマンドでは、親マシンのタスクマネージャー等で、`GPU 0`として認識されている`GPU`が仮想`GPU`として割り当てられます。

マルチ`GPU`環境で指定したい`GPU`がある場合は、下記のコマンドは実行せずに以降で紹介するコマンドを実行して下さい。

```Powershell
Add-VMGpuPartitionAdapter -VMName "仮想マシン名"
```

##### マルチ`GPU`環境での割り当てについて

マルチ`GPU`環境で`GPU 0`として、認識される`GPU`以外を割り当てたい場合、`-InstancePath`オプションで、親マシンの`Windows`で認識されるデバイスファイルパス名を指定することで`GPU`を明示的に指定することが可能になります。

このオプションは`Windows 10`のあるいはそのバージョンによっては利用できない可能性があります。

もし、利用できなかった場合は、利用したい`GPU`が、タスクマネージャー上で、`GPU 0`として認識するように、他の`GPU`を無効化する等して下さい。

マルチ`GPU`環境で、割り当てたいデバイスファイルパス名を確認する方法は下記の通りです。

```Powershell
Get-VMHostPartitionableGpu | Format-Table Name
```

下記のような結果が、返ってきます(マルチ`GPU`環境の場合、複数返ってきます)。

```Powershell
Name
----
デバイスファイルパス名
```

ここで、帰ってきた値を用いて、先程のコマンドを実行します。

```Powershell
Add-VMGpuPartitionAdapter -VMName "仮想マシン名" -InstancePath "デバイスファイルパス名"
```

#### 仮想`GPU`のリソース設定

仮想`GPU`のリソースを設定します。

物理`GPU`の全てのリソースを割り当てる場合は、以下のようなコマンドを実行します。

```Powershell
Set-VMGpuPartitionAdapter -VMName "仮想マシン名" -Passthru
```

もし、リソースを調整したい場合は、下記のようにすると明示的にパラメーターを指定できます。

```Powershell
Set-VMGpuPartitionAdapter -VMName "仮想マシン名" -MinPartitionVRAM 80000000 -MaxPartitionVRAM 100000000 -OptimalPartitionVRAM 100000000 -MinPartitionEncode 80000000 -MaxPartitionEncode 100000000 -OptimalPartitionEncode 100000000 -MinPartitionDecode 80000000 -MaxPartitionDecode 100000000 -OptimalPartitionDecode 100000000 -MinPartitionCompute 80000000 -MaxPartitionCompute 100000000 -OptimalPartitionCompute 100000000
```

その他リソースを仮想マシンに設定します。

```Powershell
Set-VM -GuestControlledCacheTypes $true -VMName "仮想マシン名"

Set-VM -LowMemoryMappedIoSpace 1GB -VMName "仮想マシン名"

Set-VM –HighMemoryMappedIoSpace 32GB –VMName "仮想マシン名"
```

### 仮想マシンに準仮想`GPU`のドライバーを追加する方法

上記の設定で既に、仮想マシンから仮想`GPU`は`PCI`デバイスの`3D controller: Microsoft Corporation Device`として見えていますが、この時点でまだ動作はしていません。

仮想マシンに、ドライバーを追加する必要があります。

この時、物理マシンに`GPU`ドライバーをインストールする場合と同じように、仮想マシンにドライバーをインストールしようとしてもできません。

この`GPU`は、通常の`GPU`とは異なる準仮想化`GPU`です。

`GPU`の一部のステータスを確認することができません。

また、カスタムカーネルのインストールの様に、準仮想化`GPU`であるため、`OS`側がこのデバイスを受け入れる様に修正する必要もあります。

そのため、ドライバーをインストールするためには、親マシンからドライバーをコピーする必要があります。

**[この仮想マシンにドライバーを追加する手順](#仮想マシンに準仮想gpuのドライバーを追加する方法)は、親マシンの`GPU`ドライバーを更新する度に行う必要があります。**

#### 親マシン上にある`GPU`ドライバーの保存場所の確認

`Powershell`で、下記コマンドを実行します。

```Powershell
Get-CimInstance -ClassName Win32_VideoController -Property * | Format-Table InstalledDisplayDrivers
```

以下のような結果が、返ってきます。

```Powershell
InstalledDisplayDrivers
-----------------------
C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_50916785244854f2\nvldumdx.dll,C:\Windows\System32\DriverStore\FileRepository\…
```

この環境での利用している`GPU`ドライバーを保存しているフォルダは、`C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_50916785244854f2\`であることがわかります。

#### 仮想マシンへのドライバーコピー

これより上の手順は、`Windows`版と共通でしたが、ここからの手順は異なります。

`Windows`上で、`wsl`フォルダを作成して下さい。

作成した、`wsl`フォルダ内に、`drivers`フォルダを作成して下さい。

`drivers`フォルダには、先程確認したドライバーのフォルダ(今回の場合、`nv_dispi.inf_amd64_50916785244854f2`)をコピーします。

次に`wsl`フォルダ内(`drivers`フォルダと同じ階層)に、`C:\Windows\System32\lxss`にある`lib`フォルダをコピーします。

これは、`WSL2`の`/usr/lib/wsl`と同じディレクトリ構造になります。

以下の`WSL2`を利用している場合コマンドを、実行したときの出力が、

```bash
ls /usr/lib/wsl
```

以下となり同じことが確認できます。

```bash
drivers  lib
```

今回の場合、コピーしてできたフォルダは、以下のような構成のディレクトリ構造になります。

```bash
wsl/
　├ lib/
　└ drivers/
　 　└ nv_dispi.inf_amd64_50916785244854f2/
```

仮想マシン上の`Ubuntu`でも、この`wsl`フォルダが同じパス、同じディレクトリ構造になるようにコピーします。

コピーの方法は、[`Linux`仮想マシンではサポートされなくなったの拡張セッション](https://github.com/Hyper-W/linux-vm-tools)や`RDP`によるコピペ(権限の問題で一旦デスクトップ等にコピーする必要やディレクトリ単位でコピーできないので`ZIP`等への圧縮が必要になります)、カスタムカーネルを公開している方の手順と同じように[`SSH Server`を有効にしての`scp`コマンド](https://github.com/brokeDude2901/dxgkrnl_ubuntu#instructions)や`sftp`コマンドによるコピー、仮想マシンの仮想ハードディスクを親マシンの`WSL2`にマウントして`WSL2`経由でコピーする等々様々な方法がありますが、好きな方法でコピーして下さい。

コピーした後は、ドライバーディレクトリの所有権や権限の設定を変更する必要があります。

仮想マシンで、以下のようなコマンドを実行します。

```bash
sudo chown -R root:root /usr/lib/wsl

sudo chmod 555 /usr/lib/wsl/lib/* 
```

ドライバーのライブラリを読み込むための設定を行います。

ドライバーのライブラリファイルがあるパスである`/usr/lib/wsl/lib`が内容のファイル`ld.wsl.conf`を`/etc/ld.so.conf.d/`に作成します。

これをコマンドで行う場合、以下の様になります。

```bash
echo "/usr/lib/wsl/lib" | sudo tee /etc/ld.so.conf.d/ld.wsl.conf
```

ライブラリを読み込む様にします。

```bash
sudo ldconfig
```

プロファイルにパスを通します。

ドライバーのライブラリファイルがあるパスである`/usr/lib/wsl/lib`をパスに追加する内容`export PATH=$PATH:/usr/lib/wsl/lib`であるファイル`wsl.sh`を`/etc/profile.d/`に作成します。

これをコマンドで行う場合、以下の様になります。

```bash
echo "export PATH=$PATH:/usr/lib/wsl/lib" | sudo tee /etc/profile.d/wsl.sh
```

作成したスクリプトに権限を与えます。

```bash
sudo chmod +x /etc/profile.d/wsl.sh
```

### カスタムカーネルのインストール

まずは、カーネルヘッダとカーネルイメージのパッケージをダウンロードする必要があります。

最新のパッケージの`URL`は、[カスタムカーネルを公開している方のリリースページ](https://github.com/brokeDude2901/dxgkrnl_ubuntu/releases/tag/main)で確認できます。

`linux-headers`から始まるファイルがカーネルヘッダで、`linux-image`から始まるファイルがカーネルイメージです。

それぞれのパッケージファイルの`URL`をファイルに対して、右クリック->リンクのコピー等で入手して下さい。

このパッケージへの`URL`を使い、以下のようなコマンドでダウンロードできます。

```bash
wget パッケージURL
```

現時点での最新版の`URL`は、カーネルヘッダが[`https://github.com/brokeDude2901/dxgkrnl_ubuntu/releases/download/main/linux-headers-5.10.102.1-dxgrknl_5.10.102.1-dxgrknl-10.00.Custom_amd64.deb`](https://github.com/brokeDude2901/dxgkrnl_ubuntu/releases/download/main/linux-headers-5.10.102.1-dxgrknl_5.10.102.1-dxgrknl-10.00.Custom_amd64.deb)、イメージが[`https://github.com/brokeDude2901/dxgkrnl_ubuntu/releases/download/main/linux-image-5.10.102.1-dxgrknl_5.10.102.1-dxgrknl-10.00.Custom_amd64.deb`](https://github.com/brokeDude2901/dxgkrnl_ubuntu/releases/download/main/linux-image-5.10.102.1-dxgrknl_5.10.102.1-dxgrknl-10.00.Custom_amd64.deb)です。

この場合は、以下のようになります。

```bash
wget https://github.com/brokeDude2901/dxgkrnl_ubuntu/releases/download/main/linux-headers-5.10.102.1-dxgrknl_5.10.102.1-dxgrknl-10.00.Custom_amd64.deb

wget https://github.com/brokeDude2901/dxgkrnl_ubuntu/releases/download/main/linux-image-5.10.102.1-dxgrknl_5.10.102.1-dxgrknl-10.00.Custom_amd64.deb
```

ダウンロードしたパッケージをインストールします。

```bash
sudo apt install -y ./ダウンロードしたパッケージ名
```

今回の場合は、以下の様になります。

```bash
sudo apt install -y ./linux-headers-5.10.102.1-dxgrknl_5.10.102.1-dxgrknl-10.00.Custom_amd64.deb

sudo apt install -y ./linux-image-5.10.102.1-dxgrknl_5.10.102.1-dxgrknl-10.00.Custom_amd64.deb
```

### `Grub`メニューからカスタムカーネルを選択できるようにする

`Grub`メニューを仮想マシン起動時に表示して、カスタムカーネルを手動で選択できる様にします。

以下のようなコマンドで表示できる様にすることが可能です。

```bash
sudo sed -i "s/GRUB_DEFAULT=0/GRUB_DEFAULT=saved/g" /etc/default/grub

sudo sed -i "s/GRUB_TIMEOUT_STYLE=hidden/GRUB_TIMEOUT_STYLE=menu/g" /etc/default/grub

sudo sed -i "s/GRUB_TIMEOUT=0/GRUB_TIMEOUT=30/g" /etc/default/grub

sudo grep -q -F "GRUB_SAVEDEFAULT=true" /etc/default/grub || echo "GRUB_SAVEDEFAULT=true" | sudo tee -a /etc/default/grub
```

修正した`Grub`の設定を適用します。

```bash
sudo update-grub
```

ここまでの設定が完了したら、仮想マシンをシャットダウンして下さい。

### カスタムカーネルを選択して起動

カスタムカーネルを選択して起動します。

まず、仮想マシンを起動する前に、仮想マシンのセキュアブートが無効になっていることを確認して下さい。

確認が終わったら起動します。

起動すると、`Grub`メニューが表示されるので、`Advanced options for Ubuntu`を選択して下さい。

![Grub_Menu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743928/cb4d4b5b-6c55-6e38-5f6d-694f9400587c.png)

次に、インストールしたカスタムカーネルを選択します。

カスタムカーネルは、末尾に`-dxgrknl`とあるものです。

今回は、`Ubuntu, with Linux 5.10.102.1-dxgrknl`を選択して起動します。

![Grub_Kernel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743928/1959fea8-5914-5e95-5306-6af3f290edec.png)

セキュアブートが有効な場合は、ここで失敗します。

無効であることを確認して下さい。

## (`Nvidia`製`GPU`限定) `nvidia-smi`コマンドによる仮想`GPU`の確認

これで、GPUを認識し、利用できるようになりました。

以下のコマンドの出力は、

```bash
lspci
```

以下の様になっていると思われますが、

```bash
なんとか 3D controller: Microsoft Corporation Device 008e
```

`Nvidia`製`GPU`の場合は、以下のようなコマンドで確認できます。

```bash
nvidia-smi
```

上記コマンドを実行すると、`WSL2`上で、このコマンドを実行した時と同じ様に一部項目は表示できませんが、コマンドの結果が正常に返ってきます(`Windows`っぽい画面に見えますが、`Windows`風にカスタムした`Kubuntu 22.04LTS`です)。

![VM_nvidia-smi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743928/fdcdf3ad-89db-52e1-3194-268f4656a9cb.png)

## (`Nvidia`製`GPU`限定) Dockerで仮想`GPU`を利用する

### `Docker`のインストール

まずは、仮想マシンをアップグレードします。

```bash
sudo apt update

sudo apt -y upgrade

sudo apt autoremove

sudo apt autoclean
```

`Docker`をインストールします。

[公式手順](https://docs.docker.com/engine/install/ubuntu/)に従います。

インストール手順に必要な依存パッケージをインストールします。

```bash
sudo apt install -y ca-certificates curl gnupg
```

`Docker`の`GPG`鍵を`apt`キーリングに追加します。

```bash
sudo mkdir -m 0755 -p /etc/apt/keyrings

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
```

リポジトリを追加します。

```bash
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

リポジトリを更新します。

```bash
sudo apt update
```

`Docker`をインストールします。

```bash
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```

`Docker`デーモンの自動起動を有効化し、動作させます。

```bash
sudo systemctl enable --now docker
```

`sudo`なしで、`Docker`コマンドを利用できる様に、ユーザーを`docker`グループに追加します。

```bash
sudo usermod -aG docker ユーザー名
```

### `NVIDIA Container Toolkit`のインストール

[公式手順](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker)に従います。

`GPG`鍵を`apt`キーリングに追加し、リポジトリを追加します。

`Ubuntu 22.04`の場合、`Ubuntu 18.04`のものが追加されます。

```bash
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
      && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
      && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
            sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
            sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
```

リポジトリを更新します。

```bash
sudo apt update
```

`NVIDIA Container Toolkit`のインストールを行います。

```bash
sudo apt install -y nvidia-container-toolkit
```

`Docker`デーモンが、`NVIDIA Container Toolkit`を認識するように構成します。

```bash
sudo nvidia-ctk runtime configure --runtime=docker
```

仮想マシンを再起動します。

```bash
sudo reboot
```

### `Docker`コンテナ内で`nvidia-smi`を実行

再起動後、仮想マシン内で、以下のコマンドを実行し、コンテナ内で、`nvidia-smi`を実行します。

`nvidia-smi`を実行するコンテナイメージをダウンロードします。

```bash
docker pull ubuntu:22.04
```

以下のコマンドで、コンテナ内で、`nvidia-smi`を実行します。

`WSL2`上で、`nvidia-smi`を実行する時等とは異なり、バインドマウントして実行する必要があります。

```bash
docker run -it --rm --gpus all -v /usr/lib/wsl/lib/nvidia-smi:/usr/lib/nvidia-smi ubuntu:22.04 nvidia-smi
```

実行すると、以下の様になります。

![VM-Docker_nvidia-smi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743928/ce6de641-0666-8739-1e42-36a9d61835ab.png)

コンテナ内でも、`GPU`を利用できることがわかります。

### `Hyper-V`仮想マシン上の`Ubuntu`上の`Docker`で`Stable Diffusion WebUI(AUTOMATIC1111)`を動かす

[こちら](https://github.com/AbdBarho/stable-diffusion-webui-docker)の`Compose`ファイルを利用します。

`WSL2`やネイティブ`Linux`上の`Docker`で実行するのと同じ手順です。

まずは、`Git`がインストールされていない場合は、インストールします。

```bash
sudo apt install -y git
```

リポジトリをクローンします。

```bash
git clone https://github.com/AbdBarho/stable-diffusion-webui-docker.git
```

クローンしたディレクトリに移動します。

```bash
cd stable-diffusion-webui-docker
```

モデル等のダウンロードを行います。

容量があるので、しばらく待ちます。

ダウンロードが終了すると、コンテナは停止します。

```bash
docker compose --profile download up --build
```

停止したコンテナを終了します。

```bash
docker compose --profile download down
```

`GPU`が必要な`Stable Diffusion WebUI`を実行します。

```bash
docker compose --profile auto up --build
```

`Running on local URL: http://0.0.0.0:7860`という内容が表示された後に、[http://localhost:7860](http://localhost:7860)にブラウザでアクセスします。

そして、プロンプトに適当な入力を与えて画像を生成します。

以下の様になっています。

![VM_Docker-Stable_Diffusion.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743928/c7242d41-bee4-468e-1ba7-dc8dbf07b799.png)

親マシンのタスクマネージャーや`HWMonitor`等で確認すると、しっかり`GPU`を利用していることがわかります。

親マシンのブラウザから[http://仮想マシンのIPアドレス:7860](http://仮想マシンのIPアドレス:7860)等で、`WebUI`にアクセスしても、`Stable Diffusion`を実行できることがわかります。

検証環境では、`mDNS`が有効なため、仮想マシンのホスト名で、アクセスして実行しています。

![VM_Docker-Stable_Diffusion_Access.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743928/ec50686e-a70f-28c9-1a1d-e261835ef048.png)

## GPU Partition Adapterの削除

**管理者権限のPowershell**で、以下のコマンドを実行します。

```Powershell
Remove-VMGpuPartitionAdapter -VMName "仮想マシン名"
```

削除すると、チェックポイントも再び使用可能になります。

`GPU`ドライバーの削除等は、別途手動で行って下さい。