技術研究所(技研)のまつけんです。

 

技研では現在、2台のゲーミングデスクトップPCにLinux (Ubuntu)とJupyterをインストールして、共有で計算(主に機械学習)サーバとして使っています。最近、計算量が増えてきたので、近いうちに3台目を購入し、セットアップする予定です。また、休眠状態だったゲーミングラップトップPCがあったので、一足先にセットアップして計算サーバ化しました。この記事では技研で確立した「機械学習用の計算サーバ構築手順」を紹介したいと思います。OSはUbuntu Server 20.04 LTSです。

※ここに記載されいてる情報は2020年9月現在のものです。また、今回のセットアップ対象は、DELLのゲーミングラップトップG5[1]です。

用意するもの

  • Ubuntu Serverのインストーラ

https://jp.ubuntu.com/download

からISOイメージを入手できます。検索エンジンで「ubuntu server iso」などを検索すれば見つかるかと思います。ダウンロードしたISOイメージのファイル名は「ubuntu-20.04.1-live-server-amd64.iso」です。

  • DVD-RドライブまたはUSBメモリ

ISOイメージファイルから起動メディアを作成します。勿論、DVD-Rに書き込むことも出来ますが、USBメモリに書き込むとスピーディにインストールできます(今回は起動からインストール完了まで3分くらいでした)。ISOファイルからUSBブートデバイスを作るソフトウェアを使います。検索エンジンで「isoファイル usbブート」などと検索すると幾つかヒットしますが、今回はインストールせずに使える「Refus 3.11 Portable」を使いました。USBメモリは7年前に購入した4 GBのもの[2]が余っていたので、それを使いました。

インストールとアップデート

インストーラの起動

USBメモリを装着し、起動します。内蔵ストレージのOSが起動してしまう場合は、再起動し、F2キーでBIOSメニューを開いてUSBから起動するように切り替えてください。

インストール

インストールは基本的にデフォルト設定で大丈夫ですが、「Install OpenSSH server」にはチェック(X)を入れます。インストール先は内蔵ストレージの「entire disk」を選べば良いのですが、「インストールできるディスクが無い」旨の表示となっていまい、今回、進まなくなってしまいました。原因はRAID設定がONなっていることでした。Ubuntu Serverでは詳しい原因がわからなかったので、Ubuntu Desktopのインストーラに切り替えて試した所、「This computer uses Intel RST (Rapid Storage Technology). You need to turn off RST before isntalling Ubuntu.」と表示されたので、BOISメニューのSystem Configuration→SATA OperationでAHCIを選択することで解決しました。

ホスト名はgiken-ml-11、初期ユーザはgiken、ネットワーク設定はDHCPです(最終的には固定IPアドレスにする)。

プロキシ設定

aptのプロキシの設定は/etc/apt/apt.confに以下の2行:

Acquire::http::Proxy "http://プロキシサーバのアドレス:ポート番号";
Acquire::https::Proxy "http://プロキシサーバのアドレス:ポート番号";

を追加することで設定します。ファイルの末尾に追加する場合は「cat >> /etc/apt/apt.conf」が便利です。必要な内容を入力またはペーストして、ctrl-dで抜けます。またwgetについて、/etc/wgetrcに以下の3行を追加します:

https_proxy = http://プロキシサーバのアドレス:ポート番号/
http_proxy = http://プロキシサーバのアドレス:ポート番号/
ftp_proxy = http://プロキシサーバのアドレス:ポート番号/

アップデート

インストールが終わったら、まず、アップデートを行って最新の状態にします:

giken@giken-ml-11:~$ sudo apt update
giken@giken-ml-11:~$ sudo apt upgrade -y

sshログインと初期設定

sshリモートログイン

リモートログインすることで、コマンドのコピー&ペーストなどが出来ます。ネットで調べ物をして、そこに載っているコマンドをそのまま実行したり出来ます。また、最終的にサーバとして使うのでsshログインが出来ないと管理するのが困難です。普段Windowsを使っている場合は、Windows側にcygwinをインストールしておくと便利です。

リモートログインするには、サーバ(giken-ml-11)のIPアドレスが必要です。今回は、ひとまずDHCPでIPアドレスを自動取得する設定でインストールしたので、ifconfigなどで調べる必要があります。ifconfigを使うには、net-toolsが必要なのでaptでインストールします:

giken@giken-ml-11:~$ sudo apt install -y net-tools

サーバのIPアドレスが192.168.0.10ならば、cygwin側からは、

cygwin:~$ ssh -l giken 192.168.0.10

のように-lでユーザ名を指定してログインします。パスワードはインストール中に設定したものを入力します。

タイムゾーン設定

タイムゾーンをアジア/東京に設定し、日付と時刻が合っていることを確認します:

giken@giken-ml-11:~$ sudo timedatectl set-timezone Asia/Tokyo
giken@giken-ml-11:~$ date
Tue 8 Sep 10:41:36 JST 2020
giken@giken-ml-11:~$

クラムシェルモード

ゲーミングラップトップをサーバとして使う場合、シェル(蓋)を閉じた状態でもサスペンドしないように設定すると便利です。この設定は/etc/systemd/logind.confで行います。このファイルに「HandleLidSwitch=ignore」を追記して、

giken@giken-ml-11:~$ sudo systemctl restart systemd-logind

を実行すると蓋を閉じてもサスペンドしなくなります[3]。デスクトップPCの場合は、この作業は不要です。

ランレベルの変更

Ubuntu Serverをインストールした直後は起動時にX Window System (以下、X)は起動せず、CUIのログイン画面となります。が、内部的には「グラフィカル」モードに設定されていて、後ほど、nvidiaのデバイスドライバをインストールすると、Xが起動するようになります。サーバとして使うのでXは不要ですから、モードを変更します[4]:

giken@giken-ml-11:~$ systemctl get-default
graphical.target
giken@giken-ml-11:~$ sudo systemctl set-default multi-user.target
Created symlink /etc/systemd/system/default.target → /lib/systemd/system/multi-user.target.
giken@giken-ml-11:~$ systemctl get-default
multi-user.target
giken@giken-ml-11:~$

かつて、この設定はrunlevelと呼ばれていて数値で管理されていて、sudo initで変更するようになていたのですが、現在はsudo initでは変更できないようです。

各種デバイスドライバ・ツールのインストール

nvidiaドライバとユーティリティ

グラフィックボードのデバイスドライバとユーティリティをインストールします。インストール後は再起動が必要です。

giken@giken-ml-11:~$ sudo apt install -y nvidia-driver-440 nvidia-utils-440 nvidia-cuda-toolkit
giken@giken-ml-11:~$ sudo shutdown -r now

Ubuntuのバージョンによっては事前に「sudo -E add-apt-repository ppa:graphics-drivers/ppa」を実行する必要があります。また、セキュアブートが有効になっている場合は、パスワード設定画面が表示されます。再起動時に「Enrol MOK」を選択して、パスワードを入力します。

再起動したら、nvidia-smiコマンドでグラフィックボードの状態が確認できることを確かめます:

giken@giken-ml-11:~$ nvidia-smi
Tue Sep 8 11:05:28 2020
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.100 Driver Version: 440.100 CUDA Version: 10.2 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce RTX 2060 Off | 00000000:01:00.0 Off | N/A |
| N/A 59C P0 16W / N/A | 0MiB / 5934MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+

なお、このとき表示される「CUDA Version: 10.2」というのは「バージョン10.2のCUDAまで利用可能」という意味であって、実際に動いているCUDAのバージョンではないようです。実際のCUDAのバージョンは、nvccで調べることが出来ます(最後の「10.1.243」の部分がバージョン番号):

matsken@giken-ml-11:~$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2019 NVIDIA Corporation
Built on Sun_Jul_28_19:07:16_PDT_2019
Cuda compilation tools, release 10.1, V10.1.243

Jupyter

Jupyterをインストールします:

giken@giken-ml-11:~$ sudo apt install -y jupyter jupyter-core jupyter-notebook

その他

その他に、動画を扱うことがあるのでffmpegとmediainfo、バージョン管理にsubversionとgit、メインのサーバから/homeをNFSマウントするのに、nfs-commonをインストールします:

giken@giken-ml-11:~$ sudo apt install -y ffmpeg mediainfo
giken@giken-ml-11:~$ sudo apt install -y subversion git
giken@giken-ml-11:~$ sudo apt install -y nfs-common

固定IPアドレスの設定

サーバとして運用するので、IPアドレスを固定します。これについては計算サーバ構築の本質とは関係ないので、詳しい説明は割愛しますが、/etc/netplan/99_config.yamlを作成しnetplan applyを実行します[5]。ただし、デバイス名が「eth0」とは限らないので、事前にifconfigで確認します:

giken@giken-ml-11:~$ ifconfig
enp60s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
    (以下略)

今回は「enp60s0」でした。

全体の設定(管理者権限での設定)は、ここまでです。ここから先は、個々人のhome directory内の設定となります。

個人設定

Jupyterの設定と動作確認

Jupyterの設定は、以下の通りです:

giken@giken-ml-11:~$ jupyter notebook --generate-config
Writing default config to: /home/giken/.jupyter/jupyter_notebook_config.py
giken@giken-ml-11:~$ sed -e s%^'#c.NotebookApp.ip = '\'localhost\'$%'c.NotebookApp.ip = '\'\*\'% -i .jupyter/jupyter_notebook_config.py

jupyter notebook –generate-configを実行すると、設定ファイル.jupyter/jupyter_notebook_config.pyが作られます。その中の

#c.NotebookApp.ip = 'localhost'

という行を

c.NotebookApp.ip = '*'

に書き換えるのですが、エディタで書き換えるより、sedで書き換えるスクリプトを作った方が、複数のユーザの設定を行うときに楽なので、sedを使っています。

設定が出来たら、Jupyterを起動します:

giken@giken-ml-11:~$ jupyter notebook
[W 17:48:19.817 NotebookApp] WARNING: The notebook server is listening on all IP addresses and not using encryption. This is not recommended.
[I 17:48:19.819 NotebookApp] Serving notebooks from local directory: /home/giken
[I 17:48:19.819 NotebookApp] The Jupyter Notebook is running at:
[I 17:48:19.819 NotebookApp] http://giken-ml-11:8888/?token=3445e22f92ae7fbec5ccb63fee938876125178a9258dc474
[I 17:48:19.819 NotebookApp] or http://127.0.0.1:8888/?token=3445e22f92ae7fbec5ccb63fee938876125178a9258dc474
[I 17:48:19.819 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[W 17:48:19.821 NotebookApp] No web browser found: could not locate runnable browser.
[C 17:48:19.821 NotebookApp]
To access the notebook, open this file in a browser:
file:///home/giken/.local/share/jupyter/runtime/nbserver-5061-open.html
Or copy and paste one of these URLs:
http://giken-ml-11:8888/?token=3445e22f92ae7fbec5ccb63fee938876125178a9258dc474
or http://127.0.0.1:8888/?token=3445e22f92ae7fbec5ccb63fee938876125178a9258dc474

サーバ側が固定IPアドレスに設定してあり、クライアント側のhostsファイルなどを設定してあれば(またはDNSなどで名前が解決できれば)、ここに表示されている「http://giken-ml-11:8888/?token=xxx」をクライアント側のブラウザで開き、Jupyterが使える筈です(DHCPのままでも「http://192.168.0.10:8888/?token=xxx」のようにIPアドレスを指定すれば使えます)。

確認が終わったら、サーバ側でctrl-cでJupyterを終了させます。

Anacondaのインストール

Anacondaのインストーラをダウンロードして実行権限を与えます:

giken@giken-ml-11:~$ wget https://repo.anaconda.com/archive/Anaconda3-2020.07-Linux-x86_64.sh
giken@giken-ml-11:~$ chmod 755 Anaconda3-2020.07-Linux-x86_64.sh

実行します:

インタラクティブなインストーラなので途中の>>>が表示されている部分(4か所)でキーボードからの入力が必要です。デフォルトのインストールを行うには順に、

  1. Enterキー (緑矢印で示した部分)
  2. yesと入力してEnterキー (赤矢印で示した部分)
  3. Enterキー (緑矢印で示した部分)
  4. yesと入力してEnterキー (赤矢印で示した部分)

です。インストールが終わったら、一度ログアウトするなどして、bashを再起動します(.bashrcが変更されているため)。

bashを再起動すると、プロンプトの前に「(base)」が表示されるようになります。この設定を解除するには、インストールの最後に表示されている通り、「conda config –set auto_activate_base false」を実行します。「conda -V」でバージョンを確認できます:

(base) giken@giken-ml-11:~$ conda -V
conda 4.8.3

また、この時点でインストールされているパッケージを控えておくと便利です[6]:

giken@giken-ml-11:~$ conda env export --name base > anaconda3/env-base.`date +%Y-%m-%d_%H-%M-%S`.yml
giken@giken-ml-11:~$ ls anaconda3
bin compiler_compat condabin conda-meta doc env-base.2020-09-08_12-03-45.yml envs etc include lib libexec LICENSE.txt man mkspecs phrasebooks pkgs plugins qml resources sbin share shell ssl translations var x86_64-conda_cos6-linux-gnu

最新版にアップデートする場合は「conda update -n base -c defaults conda」を実行します(プロキシの設定が必要な環境の場合は、先にプロキシの設定を行います)。

プロキシ設定

プロキシ設定が必要な場合は、~/.condarcの末尾に以下の3行を追加します:

proxy_servers:
http: http://プロキシサーバのアドレス:ポート番号/
https: http://プロキシサーバのアドレス:ポート番号/

TensorFlow (GPU) 環境の作成とパッケージのインストール

以下のように「conda create -n tf-gpu」を実行します:

(base) giken@giken-ml-11:/home/giken$ conda create -n tf-gpu
Collecting package metadata (current_repodata.json): done
Solving environment: done
## Package Plan ##
environment location: /home/giken/anaconda3/envs/tf-gpu
Proceed ([y]/n)?
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
# $ conda activate tf-gpu
#
# To deactivate an active environment, use
#
# $ conda deactivate

途中で「Proceed ([y]/n)? 」と聞かれるので、Enterキーを押します。インストーラのメッセージの最後に書いてある通り、この環境を有効にするには「conda activate tf-gpu」、無効にするには「conda deactivate」を実行します。続いて、「tf-gpu」の環境を有効にして、tensorflow-gpuをインストールします。「tf-gpu」を有効化するとプロンプトの「(base)」が「(tf-gpu)」に変化します。

「Proceed ([y]/n)? 」と聞かれたら、Enterキーを押します (緑矢印で示した部分、-yオプションを付ければ、この確認無しにインストールできます)。cudatoolkit、cudnn、numpy、python、scipy、tensorboard、tensorflow、tensorflow-gpuなどがインストールされていることがわかります。続いて、pythonを起動し、tensorflow.python.client.device_lib.list_local_devices()で、CPU/GPUの情報を確認します:

(tf-gpu) giken@giken-ml-11:/home/giken$ python
Python 3.8.5 (default, Sep 4 2020, 07:30:14)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> <span style="text-decoration: underline;" data-mce-style="text-decoration: underline;"><em><strong>from tensorflow.python.client import device_lib</strong></em></span>
>>> <span style="text-decoration: underline;" data-mce-style="text-decoration: underline;"><em><strong>device_lib.list_local_devices()</strong></em></span>
2020-09-08 11:18:38.190131: I tensorflow/core/platform/cpu_feature_guard.cc:143] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA
2020-09-08 11:18:38.217518: I tensorflow/core/platform/profile_utils/cpu_utils.cc:102] CPU Frequency: 2199995000 Hz
2020-09-08 11:18:38.218002: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x5565148dbee0 initialized for platform Host (this does not guarantee that XLA will be used). Devices:
2020-09-08 11:18:38.218025: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Host, Default Version
2020-09-08 11:18:38.218709: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libcuda.so.1
2020-09-08 11:18:38.706454: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:981] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2020-09-08 11:18:38.706818: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1561] Found device 0 with properties:
pciBusID: 0000:01:00.0 name: GeForce RTX 2060 computeCapability: 7.5
coreClock: 1.2GHz coreCount: 30 deviceMemorySize: 5.79GiB deviceMemoryBandwidth: 312.97GiB/s
    (中略)
2020-09-08 11:18:38.842202: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1247] Created TensorFlow device (/device:GPU:0 with 5491 MB memory) -> physical GPU (device: 0, name: GeForce RTX 2060, pci bus id: 0000:01:00.0, compute capability: 7.5)
2020-09-08 11:18:38.843718: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x5565180f7e30 initialized for platform CUDA (this does not guarantee that XLA will be used). Devices:
2020-09-08 11:18:38.843730: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): GeForce RTX 2060, Compute Capability 7.5
    (中略)
physical_device_desc: "device: 0, name: GeForce RTX 2060, pci bus id: 0000:01:00.0, compute capability: 7.5"
, name: "/device:XLA_GPU:0"
device_type: "XLA_GPU"
memory_limit: 17179869184
locality {
}
incarnation: 5683818536693192719
physical_device_desc: "device: XLA_GPU device"
]

GPUとして「GeForce RTX 2060」とVRAM 5491 MBが正しく認識されています。確認できたら、ctrl-dでPythonを終了します。

IPython Kernel for Jupyterのインストール

以下のコマンドでインストールします。例によって「Proceed ([y]/n)?」と聞かれますので、Enterキーを押します。

(tf-gpu) giken@giken-ml-11:~$ conda install ipykernel
    (中略)
Proceed ([y]/n)?
    (中略)
(tf-gpu) giken@giken-ml-11:~$ python -m ipykernel install --user --name tf-gpu --display-name "TensorFlow-GPU"
Installed kernelspec tf-gpu in /home/giken/.local/share/jupyter/kernels/tf-gpu

また、後ほどmatplotlibを使うので、ついでにインストールしておきます:

(tf-gpu) giken@giken-ml-11:~$ conda install matplotlib

Jupyterで試運転

再び、Jupyter Notebookを起動し、先程と同様にクライアント側のブラウザで「http://giken-ml-11:8888/?token=xxx」を開きます。右上の「New」から「TensorFLow-GPU」を選び、新しいnotebookを作成します:

有名な機械学習の例題MNISTを2段のDenseで学習させてみます:

無事に正解率97%の学習済みモデルが出来ました。学習がCPUではなくGPUで行われているかどうかは、nvidia-smiコマンドで確認します。最下部のジョブのリストに項目が増えている筈です(学習中であれば、消費電力も普段より大きい値になっている筈です):

+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| 0 N/A N/A 3678 C ...a3/envs/tf-gpu/bin/python 2860MiB |
+-----------------------------------------------------------------------------+

念のため、PID 3678を調べて自分のタスクであることを確認します:

(tf-gpu) giken@giken-ml-11:~$ ps aux | grep 3678
giken 3678 2.0 12.3 37314584 2019036 ? Ssl 19:31 0:27 /home/giken/anaconda3/envs/tf-gpu/bin/python -m ipykernel_launcher -f /home/giken/.local/share/jupyter/runtime/kernel-1fc031ad-4367-4b51-8b7c-08175ba938f9.json
giken 3796 0.0 0.0 13136 1148 pts/0 S+ 19:54 0:00 grep --color=auto 3678

如何でしたか? Ubuntu Linuxの新規インストールから、Anacondaを使ったMNISTをDenseで学習する実験までを通しで纏めてみました(今回のソースコードはGoogle Colaboratoryでシェアしています[7])。nvidiaのGPUを搭載したPCを機械学習用Jupyterサーバにするときなどに参考にしていただければと思います。詳しいことは、Anacondaのドキュメント[8]を参考にしてみてください。