NVIDIAのGPUのH100、A100、A30にはマルチインスタンスGPU(以降MIG)という機能が実装されています。 かつては専用ソフトウェアを使って1つのGPUを複数のGPUがあるかのように見せて、対応するアプリケーションで使うことができましたが、 先に挙げたGPUであれば追加ソフトウェア導入の必要なく、複数のインスタンスでGPUが使えます。
MIGをDockerで使ってみる
環境のセットアップ
MIGをDockerで使うには、まず、OSにDocker Engineをインストールします。 Ubuntuの場合は次のページの通りです。
その後、NVIDIA DriversとNVIDIA Container Toolkitをインストールします。
現在のバージョンのNVIDIA Container Toolkitは、Dockerの他、containerdやPodmanなども対応しています。 手順に従って、NVIDIA Container ToolkitパッケージリポジトリーとGPG keyの取り込みを行った後にインストールを行い、
$ sudo apt-get update $ sudo apt-get install -y nvidia-container-toolkit
その後次のようなコマンドを実行します。これでランタイムにNVIDIA GPUを使うための設定が行われます。
$ sudo nvidia-ctk runtime configure --runtime=docker $ sudo systemctl restart docker
これで通常はコンテナでGPUを使えるようになります。
$ sudo docker run --rm --runtime=nvidia --gpus all nvidia/cuda:12.0.0-base-ubuntu20.04 nvidia-smi
MIGを有効化
MIGをサポートするGPUで次のように実行すると、MIGがその環境で使えるようになります。
$ sudo nvidia-smi -i 0 -mig 1 Enabled MIG Mode for GPU 00000000:C1:00.0 All done.
あとはMIGのプロファイルをもとにGPUリソースを分割します。使えるプロファイルとリソースの残りは'nvidia-smi mig -lgip'というコマンドで確認できます。 まだMIGをつくる前なので、最大7つインスタンスを切ることができるようです。今回の環境はNVIDIA A100 GPU1枚が実装された環境なのでGPU 0の情報しか出力されませんが、 複数のカードが実装されている場合はそのカード分表示されます。
+-----------------------------------------------------------------------------+ | GPU instance profiles: | | GPU Name ID Instances Memory P2P SM DEC ENC | | Free/Total GiB CE JPEG OFA | |=============================================================================| | 0 MIG 1g.10gb 19 7/7 9.50 No 14 0 0 | | 1 0 0 | +-----------------------------------------------------------------------------+ | 0 MIG 1g.10gb+me 20 1/1 9.50 No 14 1 0 | | 1 1 1 | +-----------------------------------------------------------------------------+ | 0 MIG 1g.20gb 15 4/4 19.50 No 14 1 0 | | 1 0 0 | +-----------------------------------------------------------------------------+ | 0 MIG 2g.20gb 14 3/3 19.50 No 28 1 0 | | 2 0 0 | +-----------------------------------------------------------------------------+ | 0 MIG 3g.40gb 9 2/2 39.25 No 42 2 0 | | 3 0 0 | +-----------------------------------------------------------------------------+ | 0 MIG 4g.40gb 5 1/1 39.25 No 56 2 0 | | 4 0 0 | +-----------------------------------------------------------------------------+ | 0 MIG 7g.80gb 0 1/1 78.75 No 98 5 0 | | 7 1 1 | +-----------------------------------------------------------------------------+
プロファイルを使ってGPUリソースを分割していきます。プロファイルの指定方法は以下のように指定するようですが
- Profile ID (e.g. 9, 14, 5)
- Short name of the profile (e.g. 3g.20gb)
- Full profile name of the instance (e.g. MIG 3g.20gb)
例えば次のように実行すると、3つのMIGを作成できます。このプロファイルで3分割すると、もうこれ以上は分割できないようですね。
sudo nvidia-smi mig -cgi 2g.20gb -C
作成したMIGは次のコマンドにより全部削除できます。
$ sudo nvidia-smi mig -dci && sudo nvidia-smi mig -dgi
分割したGPUは次のような感じでデバイスを確認できますので
$ nvidia-smi -L GPU 0: NVIDIA A100 80GB PCIe (UUID: GPU-69198b81-f419-f843-4449-eeb123f2912f) MIG 3g.40gb Device 0: (UUID: MIG-ea2c8e7c-5712-570e-9416-bf0eda652588) MIG 3g.40gb Device 1: (UUID: MIG-0f0e3e49-8f71-5345-8a33-7c2ef0ff6bf5)
あとはDocker runコマンド実行時にUUIDを指定するだけです。
sudo docker run --runtime=nvidia \ -e NVIDIA_VISIBLE_DEVICES=MIG-ea2c8e7c-5712-570e-9416-bf0eda652588 \ nvidia/cuda:12.0.0-base-ubuntu20.04 nvidia-smi
MIGをMicroK8sで使ってみる
MicroK8sでMIGを使うのは結構簡単です。まず次のようにMicroK8sをインストールします。
$ sudo snap install microk8s --classic --channel=1.26/stable $ sudo microk8s.start $ sudo usermod -a -G microk8s $USER $ sudo snap alias microk8s.kubectl kubectl
そのあと、GPUアドオンや他に必要なアドオンがあればインストールしてください。
$ sudo microk8s enable gpu registry hostpath-storage
nvidia-mig-managerが導入されていれば、Kubernetes APIを介してMIGの設定ができます。
$ kubectl get pod -A -lapp=nvidia-mig-manager NAMESPACE NAME READY STATUS RESTARTS AGE gpu-operator-resources nvidia-mig-manager-wxbh2 1/1 Running 0 20s
例えば次のように実行すると、kubectlコマンドでMIGを設定できます。
$ kubectl label nodes shachi nvidia.com/mig.config=all-3g.40gb --overwrite node/shachi labeled
あとは次のようなマニフェストを使ってPodを作成します。nvidia.com/gpu
で指定できるのはGPU数だけですが、MIGを有効化しているのでMIGの設定で分割した数が最大値になります。
本例では2分割したので、2を指定してみましょう。
$ kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: cuda-vector-add spec: restartPolicy: OnFailure containers: - name: cuda-vector-add image: "k8s.gcr.io/cuda-vector-add:v0.1" resources: limits: nvidia.com/gpu: 2 EOF
実行するとPodが作成されて処理が行われます。ログを確認すると、アプリケーションがちゃんと実行されたのを確認できます。
$ kubectl logs cuda-vector-add [Vector addition of 50000 elements] Copy input data from the host memory to the CUDA device CUDA kernel launch with 196 blocks of 256 threads Copy output data from the CUDA device to the host memory Test PASSED Done
nvidia.com/gpu: 3
にして実行すると、GPU要求を環境が満たしていないためPending
になり、次のようなイベントが記録されます。
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 11s default-scheduler 0/1 nodes are available: 1 Insufficient nvidia.com/gpu. preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod..
CPUとは異なりGPUにはコアがたくさんあります。メモリーについてはGPUに実装されているメモリーを均等に分割していきますので、 分割したリソースに割り当てられるメモリーはチップに載っているメモリーサイズ次第です。
アプリケーション開発などでGPUを使う場合に複数のアプリケーションでGPUが使えて便利な機能だと思います。