遠隔地からの機械学習環境利用

# はじめに
　GPUサーバにリモート接続し、エッジデバイスにフィードバックする方法を検討しています。まずは、GPUサーバにSSHでアクセスし、機械学習をリモートで実行するための環境を構築し、その学習結果を自宅の作業環境にあるjetson及びkriaで推論できる方式を検討します。

# 作業環境
* ネットワーク（IPv4overIPv6）
* GPUサーバ(Ubuntu: 20.04.3 LTS Focal Fossa)
  * Kubernetes
  * Docker 
* Mac(macOS Big Sur: バージョン11.6)
  * XQuartz
  * Docker Desktop 

# 作業条件
* 大阪（遠隔端末）から北海道（GPUサーバ）という遠隔での作業
* 作業者２名
* 機械学習環境を共有する必要がある

# 環境構築
　作業条件からDockerを用いて、機械学習環境のベースは同じにしておき、何か特別なことを実行したい場合は新たにコンテナを生成し、そこで作業を行うことにしたいと考えています。特に、Pythonや関連するライブラリのインストールによってそれまでのスクリプトが動作しなくなるということを懸念しています。
　また、コンテナがある程度増えるということを見越して、Kubernetesを用いた簡単なコンテナ管理を行いたいと考えています。将来的には、AWSやGcpで構築した環境も同じKubernetesで管理することを検討したいと思います。

![dockerNetwork.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423321/13a5e53d-2b58-2b8e-3d04-7c6038d400c5.jpeg)

　この環境下では，ユーザは，以下のような条件下でGPUサーバを使用する必要があります。

* 各機械学習環境は，必要に応じて，各ユーザがコンテナを立ち上げ，それを利用する
 * 今後の状況によっては，同一環境を使うことも可能だが，ssh接続中に時々broken pipeし，起動時のdockerプロセスが落ちることがある。
* コンテナ内で必要なリソースについては，独自でダウンロードしてそれを用意する
* 学習結果等，非常に時間がかかるものについては，データの永続化を検討する必要がある。

## 0　SSH接続とディスク共有

* 凡例及び条件

~~~
[凡例]
hoge            :  ユーザ名
portNum         :ポート番号（ssh）
xxx.xxx.xxx.xxx :ipアドレス
~/MOUNT         :マウント対象

[条件]
事前に端末及びサーバ間でsshに用いられる鍵交換ができていること
~~~

* 事前準備

~~~mac:事前のインストール
brew install macfuse
brew install gromgit/fuse/sshfs-mac
~~~

~~~ssh:GPUサーバへの公開鍵登録
ssh-copy-id hoge@xxx.xxx.xxx.xxx -p portNum
~~~

* ssh接続（X11使用前提）

~~~ssh:ssh接続
ssh -X -p portNum hoge@xxx.xxx.xxx.xxx
~~~

* 遠隔ディスクのマウント

~~~ssh:sshfsによるマウント
sshfs -o IdentityFile=~/.ssh/id_rsa hoge@xxx.xxx.xxx.xxx:/home/hoge ~/MOUNT -p portNum
~~~

* マウントが外れた場合のゴーストディスク削除

~~~ssh:mountが外れた場合
sudo diskutil umount force ~/MOUNT
rm -r ~/MOUNT
~~~

* KeepAlive設定

~~~ssh:サーバ側設定
sudo vim /etc/ssh/sshd_config
ClientAliveInterval 120
ClientAliveCountMax 3
~~~

## 1　GPUサーバへのDockerエンジンの構築
[公式ページ](https://docs.docker.com/engine/install/ubuntu/)を参考にDocker環境の構築を行います。今回はrepositoryから直接インストールを行っています。
念のため、Dockerエンジンが正しく動作していることを以下のコマンドで確認する

~~~
docker --version
~~~
## 2　GPUサーバへアクセスするための遠隔端末の準備
こちらも同様に[公式ページ](https://hub.docker.com/editions/community/docker-ce-desktop-mac)から何も考えずにインストールできます。

* 同様に、Docker Desktop 環境が正しく動作していることを以下のコマンドで確認する

~~~
docker --version
~~~

* また、リモートでGPUサーバに接続し、以下のコマンドでDocker版のHello Worldを確認する

~~~
sudo docker run hello-world
~~~
CentOS等と異なり、ubuntuでは、原則sudoが必須となる。

* 遠隔でGIMP等のUI動作できるようにXQuartzをインストールする
　[公式ページ：XQuartz](https://www.xquartz.org)からインストールする。ssh接続時に-Xオプションをつければ立ち上がるようになる。xeyesやGIMPがコマンドラインから立ち上がることを確認する。

~~~
xeyes
~~~

## 3　nvidiaのサンプルプログラムを動かす
1. nvidiaのサンプルプログラムが[公式サイト](https://catalog.ngc.nvidia.com/)にあるため，それを動作させる（CNNで検索した例）。
![nvidia_catlogtop.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423321/af38255c-7921-0f11-5f8b-61fe57a53242.jpeg)

2. 今回はPytorch用のクイックスタートガイドを選択する
![nvidia_pytorch.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423321/22672626-2671-aa24-9150-a6abc03c994d.jpeg)

3. このサンプルでは，以下のような作業順序となる
 (1) gitからデータをローカルにクローンする
 (2) DeepLearning用の評価画像をCOCOというサイトからダウンロードする
 (3) Pytorch用のMask R-CNN NGC コンテナを起動する
 (4) 学習を開始する
 (5) 学習に対する評価を行う
 (6) 推論を行う 

4. ハマりポイント
 (1) GPU数の変更を変更する
（GPU=8->1,train.sh/inference.sh/eval.sh）
 (2) dtrxを使用できないため、自分で解凍する
 (3) 推論パラメータの変更
（TEST.IMS_PER_BATCH:1->10,inference.sh）

# 課題
## 1　docker特有の課題
　dockerをubuntu上で使用するとsudo権限が必要となり，docker内の制御が全ユーザroot権限になってしまいます。そのため，不特定多数の作業者環境には向かないという状況があります。一方，そのための代替として，Singularityのようなツールもありますが，以下のような問題があります。

* 今回のようにベンダーが提供する機械学習環境がDockerをベースに構築されている
* Dockerfileの互換性の問題等で環境構築時に苦労する可能性がある
* DockerImageをそのまま利用はできない（変換が必要となる。）。

　今回は，まず立ち上げということもあり，セキュリティリスク及び効率的な共有環境というのを犠牲にしています。今後，SinguralityやSlurmについては，検討が必要です。

## 2　ubuntuの特定リビジョンでdtrxが使えない
　１つ目の課題と比べると大したことではないですが，NVIDIAでは素材を収集し，tar, gz, zip等を自動で判断して，結合・解凍するツールとしてdtrxというツールを使用しているが，ubuntuの20.04 LTS Focal Fossaでは公開されていないため（21系列からは復活している），独自で解凍等を行う必要がある。

# 参考
* IPv4overIPv6の設定  
[V6プラスのポート開放](https://iori016.hatenablog.com/entry/ar1996312)
* 公開鍵をホストに登録する際の秘密鍵パーミッションエラー対処  
[SSH接続しようとしたら秘密鍵のパーミッションエラーがでた](https://qiita.com/maikya_gu/items/307cc98ec07c7b8bce72)