Study Summary - GPU

Page content

GPUの性能を決めるハードウェア的要素

CUDA コア数 (≒ GPUのコア数. 2000-4000 もある), メモリ (3)次元以上の多次元配列ではメモリ消費量が大), 消費電力, 単精度浮動小数点数演算性能(FP32. clock数や FLOPS/clock が影響)

image-20210907224824956

GPUで並列処理させると速いっていう体験

とても簡単な例だけど、 pyCUDA でプログラム書く on Google Colab をやってみた。

# pip3 install pycuda されている必要がある

# ライブラリ読み込み
import numpy as np
import pycuda.gpuarray as gpuarray
from pycuda.elementwise import ElementwiseKernel
import pycuda.autoinit

# pyCUDA kernel の定義. for 文の定義が不要なのが特徴的
plus_one_kernel = ElementwiseKernel(
    "int *y, int *x",  # argument
    "y[i] = x[i] + 1", # カーネルの実行内容
    "plus_one"         # カーネル名
)

# GPU に渡す配列を用意する
num_components = 10
x = np.arange(num_components, dtype=np.int32)
x  #=> array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32)

# CPU から GPU にデータを送る
x_gpu = gpuarray.to_gpu(x)  # 送り方その1
y_gpu = gpuarray.zeros(num_components, dtype=np.int32)  # 送り方その2

# 実際に kernel に送って実行する
plus_one_kernel(y_gpu, x_gpu)

# このままだと GPU mem 上にあるので CPU mem に持ってくる
x_gpu.get()  #=> array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32)
y_gpu.get()  #=> array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype=int32)

GPU 周りのソフトウェアスタック理解

OpenACC / OpenMP
CUDA / OpenCL
PTX / SPIR-V
(GPUドライバ?)
GPUハードウェア
  • PTX: GPUハードウェアの機械命令に近いレベルの命令の記述. アセンブラのレベル. CUDA コンパイラの出力
  • CUDA: GPU向けのプログラミングでよく使われる言語 (C言語の拡張). しかしこれでも CPU-GPU間のデータ転送などを明示的に記述する必要があり、プログラミングが難しいとされる
  • OpenACC, OpenMP: CUDA や OpenCL のような GPU 向けC言語拡張 をさらにラップする 自動並列化ツールもある

ドライバ

PTX で記述されたプログラムを、使用しているGPUの機械命令に変換する。

Host OS へのインストールは apt-get install のようにパッケージマネージャで cuda-drivers パッケージを入れる。(正確には公式を参照)

docker コンテナで利用するために必要なこと

この絵がわかりやすいと思いきやチョット違って困る。 nvidia-container-toolkit

テキストだが、こんな感じになる

    +----------------+
    |  applications  |
    |  CUDA toolkit  |  <-- CUDA container が解の一つ
    +-- container ---+
+--------------------------+
| NVIDIA Container Toolkit |  <-- 別名 nvidia-docker2. ホストOSに入れるのが大事
|      docker engine       |
|      NVIDIA Driver       |
+-------- host OS ---------+
+--------------------------+
|       NVIDIA GPUs        |
+------- bare metal -------+
  • NVIDIA Container Toolkit はパッケージマネージャーでは nvidia-docker2 という名前になっている(正確には installation guide を参照)
  • コンテナは nvidia/cuda などの docker image を使えば、 CUDA Toolkit 入りのものが使える

k8s で GPU を利用するために必要なこと

k8s で GPU や Infiniband などの特別なハードウェアデバイスを利用するためには Device Plugin Framework を通してそれを実現する。

GPU の利用を超凝縮すると:

  • クラスタ一括導入ではなく、ノードごとに導入の操作が必要 (デバイスプラグインのインストール + その前段の準備)
  • オーバーコミットは出来ず、コンテナ間で同じ GPU を共有することは出来ない。
  • コンテナは 1つ以上のGPUをリクエストできる。 1 GPU の一部分だけをリクエストすることは出来ない。

デバイスプラグインインストール前の準備:

  • Kubernetesのノードに、NVIDIAのドライバーがあらかじめインストール済みでなければならない。
  • Kubernetesのノードに、nvidia-docker 2.0があらかじめインストール済みでなければならない。
  • KubeletはコンテナランタイムにDockerを使用しなければならない。
  • runcの代わりにDockerのデフォルトランタイムとして、nvidia-container-runtimeを設定しなければならない。
  • NVIDIAのドライバーのバージョンが次の条件を満たさなければならない ~= 384.81。
  • クラスターが起動して上記の要件が満たされれば、以下のコマンドを実行することでNVIDIAのデバイスプラグインがデプロイできます。

デバイスプラグインのインストール方法:

kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/1.0.0-beta4/nvidia-device-plugin.yml

参考:

NVIDIA GPU Operator

operator framework

  • pattern for developing k8s-native apps
  • encode operational knowledge to automate administration tasks

k8s で GPU を扱う多くを自動管理してくれる。具体的には

  • いろいろなソフトウェアコンポーネントの自動管理

    … include the NVIDIA drivers (to enable CUDA), Kubernetes device plugin for GPUs, the NVIDIA Container Toolkit, automatic node labelling using GFD (GPU Feature Discovery), DCGM (NVIDIA Data Center GPI Manager) based monitoring and others.

  • プラットフォームも色々サポートしている(クラウド含め)

とは言え事前にやることはあって、

  • k8s インストール
  • container engine に指定がある
  • NVIDIA vGPU Host Driver のインストールが必要, ライセンスサーバも必要
  • 等々

がある。その後 Helm chart を使ってインストールする。 NVIDIA GPU Operator の導入方法は 公式ドキュメント 参照

GPU が活躍する ML, DL 事例理解

Deep Neural Network では王道的に活躍するよね。 ML/DL に限らなければ 3D グラフィックスで車内内装やインテリア設計, VR/AR で部品整備時の注意箇所をオーバーレイ表示するとか, スパコンとか (GPUではなく専用ハードウェアデバイスを用意することもありつつ)

参考文献

  • GPUを支える技術 (Kindle)
  • Python で学ぶ CUDA プログラミング入門 (Udemy)