本記事の前提
- Ubuntu Server 21.04 がセットアップされている
- NVIDIA 製の GPU がマシンに搭載されている
事前確認
そもそも何の GPU が挿さっているのか知らなかったので、まずはそれの確認からです。
$ lspci | grep -i nvidia
01:00.0 VGA compatible controller: NVIDIA Corporation TU117 [GeForce GTX 1650] (rev a1)
01:00.1 Audio device: NVIDIA Corporation Device 10fa (rev a1)
NVIDIA の GeForce GTX 1650 でした。
1年前に買ったマシンなのですが、本記事の執筆時点でも最新のゲームが遊べる程度にはしっかりとした性能のようでした。正直しらんかった(無関心)
次に、起動ログを確認し「nouveau(ヌーヴォー)」が暫定ドライバとして読み込まれていることを確認します。
$ sudo dmesg | grep -i nouveau
[ 1.517791] fb0: switching to nouveaufb from EFI VGA
[ 1.520475] nouveau 0000:01:00.0: vgaarb: deactivate vga console
[ 1.520537] nouveau 0000:01:00.0: NVIDIA TU117 (167000a1)
...(後略)
確かに、nouveau が GPU ドライバとして初期インストールされています。
ちなみに、nouveau を Wikipedia で調べると**「現在は NVIDIA のプロプライエタリな Linux 用ドライバをリバースエンジニアリングして、 NVIDIA のビデオカード用のフリーなドライバを開発することを狙いとしている」**と書いてあって、OSS 開発の天才たちが、儲かってる巨大企業をグーで殴りにいくアベンジャーズ感がすごくてステキでした。いいぞ!もっとやれ!!
……まあ、とはいえ、普通に NVIDIA の純正ドライバを入れるんですけどね。
次に、ubuntu-drivers
で搭載している GPU の推奨ドライバを確認します。
$ ubuntu-drivers devices
== /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0 ==
modalias : pci:v000010DEd00001F82sv0000103Csd00008558bc03sc00i00
vendor : NVIDIA Corporation
model : TU117 [GeForce GTX 1650]
driver : nvidia-driver-418-server - distro non-free
driver : nvidia-driver-450 - distro non-free
driver : nvidia-driver-450-server - distro non-free
driver : nvidia-driver-460 - distro non-free recommended
driver : nvidia-driver-460-server - distro non-free
driver : xserver-xorg-video-nouveau - distro free builtin
推奨ドライバが「nvidia-driver-460」であることが確認できました。
ちなみに、このコマンド用のパッケージ ubuntu-drivers-common
は、Ubuntu Server には初期インストールされていないので、apt でインストールしておきましょう。
ドライバのインストールと読み込み確認
一応、apt のレポジトリを更新し、現在マシンにインストールされている全部のパッケージを最新版にしておきます。
$ sudo apt-get update
$ sudo apt-get upgrade
で、インストールなのですが、私の環境では、次のコマンドで入りました。
$ sudo ubuntu-drivers autoinstall
ものすごい勢いでさまざまなパッケージがインストールされていくので、端末がログまみれになるのをコーヒーでも飲みながら眺めましょう。
さて、デバイスドライバを組み込んだので、まずはマシンを再起動します。
忘れがちですが必須です。
$ sudo reboot
インストール後の確認
再起動後、きちんとドライバが読み込まれていることを確認します。
まずは、nouveau ではなく、NVIDIA 純正ドライバが起動時に読み込まれていることを確認します。
$ sudo dmesg | grep -i nouveau
(結果なし)
$ sudo dmesg | grep -i nvidia
...(前略)
[ 6.420835] nvidia: loading out-of-tree module taints kernel.
[ 6.420843] nvidia: module license 'NVIDIA' taints kernel.
[ 6.437721] nvidia-nvlink: Nvlink Core is being initialized, major device number 511
[ 6.438240] nvidia 0000:01:00.0: vgaarb: changed VGA decodes: olddecodes=io+mem,decodes=none:owns=io+mem
[ 6.481330] NVRM: loading NVIDIA UNIX x86_64 Kernel Module 460.73.01 Thu Apr 1 21:40:36 UTC 2021
[ 6.499844] nvidia-modeset: Loading NVIDIA Kernel Mode Setting Driver for UNIX platforms 460.73.01 Thu Apr 1 21:32:31 UTC 2021
...(後略)
次に、$ lsmod | grep -i nvidia
でドライバが読み込まれていることを確認します。
$ lsmod | grep -i nvidia
nvidia_uvm 1032192 0
nvidia_drm 57344 3
nvidia_modeset 1228800 5 nvidia_drm
nvidia 34131968 191 nvidia_uvm,nvidia_modeset
drm_kms_helper 245760 1 nvidia_drm
drm 552960 6 drm_kms_helper,nvidia_drm
また、組み込まれたドライバの種類も確認しておきましょう。
$ ubuntu-drivers list
nvidia-driver-450-server, (kernel modules provided by linux-modules-nvidia-450-server-generic)
nvidia-driver-460, (kernel modules provided by linux-modules-nvidia-460-generic)
nvidia-driver-418-server, (kernel modules provided by linux-modules-nvidia-418-server-generic)
nvidia-driver-460-server, (kernel modules provided by linux-modules-nvidia-460-server-generic)
nvidia-driver-450, (kernel modules provided by linux-modules-nvidia-450-generic)
(460 以外にも 450, 418 が組み込まれている理由は分からない…)
最後に、nvidia-smi
で次のような結果が返ってくることを確認します。
$ nvidia-smi
Mon May 10 04:13:41 2021
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 460.73.01 Driver Version: 460.73.01 CUDA Version: 11.2 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 GeForce GTX 1650 Off | 00000000:01:00.0 On | N/A |
| 30% 32C P8 4W / 75W | 81MiB / 3889MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| 0 N/A N/A 1249 G /usr/lib/xorg/Xorg 71MiB |
| 0 N/A N/A 1476 G /usr/bin/gnome-shell 7MiB |
+-----------------------------------------------------------------------------+
CUDA コンパイラドライバのインストール
NVIDIA がバイナリパッケージを配布してくれているおかげで、apt 一発でインストールされました。
$ sudo apt-get install nvidia-cuda-toolkit
きちんとインストールされていることを確認します。
$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2021 NVIDIA Corporation
Built on Sun_Feb_14_21:12:58_PST_2021
Cuda compilation tools, release 11.2, V11.2.152
Build cuda_11.2.r11.2/compiler.29618528_0
やっぱ NVIDIA 神っすよ。さっきはグーで殴るとか言ってごめんね。
実行時間の確認
GPU は本当に使えるようになったのか?
数値計算の速度は上がっているのか?
その謎を探るべく我々はアマゾンの奥地に……は向かいませんが、とりあえず次のプログラムを動かしてみることにしました。
import numpy as np
import cupy as cp
import time
N = [1000, 5000, 8000, 10000]
for n in N:
start = time.time()
W_cpu = 2 * np.random.rand(n, n) -1
inv_W_cpu = np.linalg.inv(W_cpu)
print ("CPU: elapsed_time:{0}".format(time.time() - start) + "[sec]")
start = time.time()
W_gpu = 2 * cp.random.rand(n, n) -1
inv_W_gpu = cp.linalg.inv(W_gpu)
print ("GPU: elapsed_time:{0}".format(time.time() - start) + "[sec]")
つまり、1000, 5000, 8000, 10000 次元における逆行列の計算時間を、CPU と GPU で比較しようということです。
結果は次のとおりでした(単位は秒、有効数字は小数点以下3桁)
CPU | GPU | |
---|---|---|
1000 | 0.029 | 0.645 |
5000 | 1.730 | 0.990 |
8000 | 6.521 | 3.546 |
10000 | 12.150 | 7.500 |
1000 次元程度では、CPU と GPU でデータをやり取りするオーバヘッドが大きいせいか、逆に遅くなっていますが、次元が大きくなるにつれて GPU の方が速くなっています。
また、10000 次元の逆行列の計算中に $ nvidia-smi
を実行すると、プロセス名に「python3」が表示されます。
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 460.73.01 Driver Version: 460.73.01 CUDA Version: 11.2 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 GeForce GTX 1650 Off | 00000000:01:00.0 Off | N/A |
| 30% 42C P0 36W / 75W | 3588MiB / 3889MiB | 100% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| 0 N/A N/A 2057 G /usr/lib/xorg/Xorg 134MiB |
| 0 N/A N/A 2192 G /usr/bin/gnome-shell 6MiB |
| 0 N/A N/A 7534 C python3 3443MiB |
+-----------------------------------------------------------------------------+
温度も消費電力も消費メモリも上がっているので、動いてるっぽいですね。
ちなみに、このプログラムはパッケージ管理まわりも含めて GitHub で公開しているので、次のコマンドを叩いて使ってみてください。
$ make install
$ make
メモリが足りねえ
10000 次元の逆行列の計算中、GPU 計算ではメモリが足りなくてプログラムが停止することが何回かありました。この GeForce GTX 1650 には 3889 MiB = 約 4 GB のメモリしか載っておらず、数値計算のキャッシュが追いつかないためと考えられます。
本当に実用的な数値計算に使えるのか?
実際の現場で「AI 用計算機」としてどれほどパフォーマンスを発揮できるのか?
その謎を探るべく我々はアマゾンの奥地に……は向かいませんが、とりあえずユニファイドメモリの導入などを検討しましょう。
それにしても、10000 次元の逆行列が、10 秒程度で計算できるようになるとは……恐ろしい時代が来たもんですね。そりゃディープラーニングも流行るわけだ。
デバッグ?
Error: no integrated GPU detected
私の環境では、$ sudo ubuntu-drivers autoinstall
すると、最後に次のようなエラーメッセージが出ました。
Error: no integrated GPU detected.
「統合された GPU が見つからないよ」というエラーなのですが、おそらく(あくまで推測ですが)、GPU が1枚しか挿さっていないため表示されたエラーだと思います。
つまり、「1枚しか挿さってないから複数枚を統合させて動作するわけじゃないよ」と。なので、Error というより Warning かなと思ってます。
実際、インストール後の確認結果は、上記のように動いてるっぽい結果が出力されるので、まあ、たぶん、、、いいのかなと。もしこのあたりに認識違いがあれば、エロい人に教えて欲しいです。
FileNotFoundError: [Errno 2] No such file or directory: 'aplay'
上記のとおり $ ubuntu-drivers list
を実行すると、このエラーが出ました。
$ ubuntu-drivers list
ERROR:root:could not open aplay -l
Traceback (most recent call last):
File "/usr/share/ubuntu-drivers-common/detect/sl-modem.py", line 35, in detect
aplay = subprocess.Popen(
File "/usr/lib/python3.9/subprocess.py", line 951, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "/usr/lib/python3.9/subprocess.py", line 1821, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'aplay
nvidia-driver-450-server, (kernel modules provided by linux-modules-nvidia-450-server-generic)
... (後略)
おそらく、サウンド関連のデバイスドライバがうまくいってないせいで出ているのかなと推測してます。サーバ用途でマシンを使うので、サウンドなんぞいらんから無視しました。
(補足) 謎の「Automatic suspend」をオフにする
これは本記事の趣旨とは外れるのですが、、、(というより、自分用のメモ)
NVIDIA のドライバと依存関係にある GUI 関連のパッケージもインストールされるので、マシンを再起動させた時点で、Ubuntu Server で簡易なデスクトップ環境が使えるようになります。
この GUI を利用して、Ubuntu Server の自動サスペンドをオフにしておきましょう。これをしなければ、サーバなのに 20 分操作がなかった時点で、本体ボタンを押さないとスリープ解除されないという意味のわからないことになります。
ディスプレイを直接カメラ撮影した雑な画像ですが……上記項目の「Automatic Suspend」を「Off」にしておきます。