機械学習用のLinuxインスタンスの環境構築(GCEやEC2などクラウド)

概要
最近では機械学習の計算のためにLinuxマシンを構築しては消し、を繰り返すことが多い。サーバの構築と消去が柔軟に可能なことからもEC2やGCEなどクラウドのインスタンスをよく使うということも影響している。 この記事では一般的なサーバ構築の記事では紹介されていない、クラウドのインスタンスで意外と盲点になる点を中心に、機械学習の計算用サーバとして安定した運用をするために最低限必要な設定をまとめた。 GPUドライバ(CUDA、cuDNN)やコンテナランタイム(Docker/NVIDIA Container Toolkit)の設定は別途必要となる。
Linuxで最初にやっておくべき設定
Amazon EC2やGoogle Compute Engineなどのクラウドインスタンスのデフォルトの設定では不都合があるため、設定を追加する必要がある。
スワップメモリの設定
クラウドのインスタンスではデフォルトでスワップメモリが設定されていないため、念のため設定しておく必要がある。以下は/swap.imgとして4GBのスワップファイルを設置する例。
sudo sh -c 'dd if=/dev/zero of=/swap.img count=4096 bs=1MiB && chmod 600 /swap.img && mkswap /swap.img && swapon /swap.img'
スワップのされやすさをswappinessというパラメータで0~100の数値で指定する。値が大きいほどスワップされやすくなる。デフォルトで60となっているが、これを10に変更(スワップされにくくする)するには
sudo sysctl vm.swappiness=10
確認
cat /proc/sys/vm/swappiness
再起動時に自動で有効化するには
echo '/swap.img none swap sw 0 0' | sudo tee -a /etc/fstab
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
タイムゾーンの設定
デフォルトのタイムゾーンがUTCなのでJSTに設定しておく。 RHEL系(RHEL7以降)、Ubuntuでは
sudo timedatectl set-timezone Asia/Tokyo
SELinuxの無効化
SELinuxが有効になっていると不都合なことが多いので、有効な場合は無効化する。 SELinuxが有効かどうかの確認
getenforce
Enforcingだと有効になっている。
一時的に無効化する場合
sudo setenforce 0
永続的に無効化する場合は
sudo vi /etc/selinux/config
SELINUX=disabled
とする。
カーネルパニックは10秒後に再起動
# 一時的
sudo sysctl kernel.panic=10
# 永続的
sudo sh -c "echo 'kernel.panic = 10' >> /etc/sysctl.conf && sysctl -p"
OOM killerが出ないようにする
# 一時的
sudo sysctl vm.overcommit_memory=2
# 永続的
sudo sh -c "echo 'vm.overcommit_memory=2' >> /etc/sysctl.conf && sysctl -p"
これでもOOM killerは少しは発生するが、特定のプロセスに対して絶対発生させないようにするためには
echo -1000 | sudo tee /proc/プロセスID/oom_score_adj
oom_adjは非推奨のため、oom_score_adjを使用する。-1000を指定するとOOM killerの対象から除外される。
起動時スクリプトの設定
これらのコマンドをシステム起動時に自動実行するには、systemdのservice unitを作成する。
/etc/rc.localは非推奨のため使用しない。
例:/etc/systemd/system/my-startup.service
[Unit]
Description=My startup script
After=network.target
[Service]
Type=oneshot
ExecStart=/path/to/startup.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable my-startup.service
Redhat系Linux、Debian系Linux、MacOSのパッケージ管理ツールの比較
- Redhat系(RHEL, Rocky Linux, AlmaLinuxなど)
- Debian系(Debian, Ubuntuなど)
- Mac(Homebrew)
| yum/dnf | apt | Homebrew | |
|---|---|---|---|
| インストール | yum install packagename / dnf install packagename | apt-get install packagename | brew install packagename |
| アンインストール | yum remove packagename / dnf remove packagename | apt-get remove packagename | brew uninstall packagename |
| 名前で検索 | yum search keyword / dnf search keyword | apt-cache search keyword | brew search keyword |
| 含まれるファイル名で検索 | yum provides filename / dnf provides filename | apt-file search filename | |
| 全更新 | yum upgrade / dnf upgrade | apt-get dist-upgrade | brew upgrade && brew cleanup |
| インストール済み一覧 | yum list installed / dnf list installed | apt list –installed | brew list |
Homebrewの場合、インストール直後には実行バイナリが自動で$PATHに追加される。
Google Cloud Storageのマウント
Google Cloud Storage上にデータファイルや学習済みモデルなどの大きなファイルを格納するが、
gsutilコマンドではなく通常のローカルファイルと同様にコマンドラインで扱えるようにしたい。
そこでGCS上のバケットをローカルのディレクトリにマウントするツールであるgcsfuseを使う。
gcsfuseのインストール
https://github.com/GoogleCloudPlatform/gcsfuse/blob/master/docs/installing.md のとおり。
gcsfuseコマンドの使い方
ローカルにマウントポイントとなるディレクトリを作成し、指定のバケットをマウントする。
gcsfuse バケット名 マウントポイント
このままではバケット直下のファイルにしかアクセスできない。バケット内のフォルダにアクセスできないのだが、mkdirコマンドで空のディレクトリを作ることで、その中のファイルにアクセスできるようになる。たとえばgs://バケット名/my_folderの中身にアクセスできるようするには
mkdir マウントポイント/my_folder
個別にmkdirせずに全てのサブディレクトリも同時に読み込めるようにするには、マウント時に
gcsfuse --implicit-dirs バケット名 マウントポイント
デフォルトでキャッシュが効くため、ファイルの更新が反映されにくい。キャッシュを無効にするには
gcsfuse バケット名 マウントポイント --stat-cache-ttl 0 --type-cache-ttl 0
アンマウントするには
fusermount -u マウントポイント
EC2などのGCE以外の環境では環境変数$GOOGLE_APPLICATION_CREDENTIALSにcredentialを明示的に指定しておく必要がある。
export GOOGLE_APPLICATION_CREDENTIALS=/home/my_user/service-account.json
これを~/.bash_profileなどに記述しておいてあらかじめ実行されるようにしておくといい。
