Marketechlabo

機械学習用の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/dnfaptHomebrew
インストールyum install packagename / dnf install packagenameapt-get install packagenamebrew install packagename
アンインストールyum remove packagename / dnf remove packagenameapt-get remove packagenamebrew uninstall packagename
名前で検索yum search keyword / dnf search keywordapt-cache search keywordbrew search keyword
含まれるファイル名で検索yum provides filename / dnf provides filenameapt-file search filename
全更新yum upgrade / dnf upgradeapt-get dist-upgradebrew upgrade && brew cleanup
インストール済み一覧yum list installed / dnf list installedapt list –installedbrew 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などに記述しておいてあらかじめ実行されるようにしておくといい。