Edited at

Azure Batch AI - Chainer MNをInfiniband / GPU付きノードで高速並列実行する!

More than 1 year has passed since last update.

Azure Batch AI - AzureでGPU/マルチノードでディープラーニング計算を簡単に行う!(Chainer MN編)

https://qiita.com/YoshiakiOi/items/2f143e62bcf5d7daa8e9 に続いて、Batch AIを使っていきます。

今回はChainer MNのジョブを、AzureのInfiniband付き(もちろんGPUも!)ノードで並列実行していきます!


Batch AIとは?

前項参照。

https://qiita.com/YoshiakiOi/items/2f143e62bcf5d7daa8e9

ディープラーニングの学習を、オンデマンドでたくさんGPU付きノードを並べたクラスターを作成して、簡単に並列実行できるようにする、Microsoft Azureの1製品。

今回はInfinibandを利用して、より高速に実行できる環境を作っていきます。


Infinibandとは?

主にHPC (High Performance Computing、大量の計算資源を利用して、大量・高速なコンピューティングを行う分野)で利用される、低待機時間・広帯域な通信規格。

MPIをInfiniband経由で実行すると、ノード間通信が高速になり、ノードを並列に並べたときにスケールするようになります(もちろんコードによりますが)。

MicrosoftのAzureでは、クラウドから一部の仮想マシンでInfinibandを利用することができます。


注意点

AzureでMPIからInfinibandを利用するには、2018年現在、Intel MPI、Platform MPI、MS MPIを利用する必要があります。本稿では、Intel MPIを利用して、Chainer MNを実行します。


(参考)

[Azure Antenna] HPCだけじゃないDeep Learningでも使える ハイパフォーマンスAzureインフラ ~ HPC and Deep Learning on Azure ~

https://www.slideshare.net/ShuichiGojuki/hpc-on-azure21


Chainer MN on Azure GPU/Infiniband Nodes

Batch AI上ではありませんが、Chainer MNをAzureのGPU/Infinibandノードで実行すると、ノード数を増やしてもスケールする(ノードを増やした分だけ線形的に実行時間が短くなる)ことが、発表されています。


(参考)

de:code 2018 Online AI05 AI ChainerMN on Microsoft Azure で大規模分散深層学習

https://info.microsoft.com/JA-CNTNT-eBook-decode18Online-MGC0002650_01Registration-ForminBody.html

Batch AIは、Azureの上記のような高性能なインフラをなるべく簡単にディープラーニングに利用するためのPaaS型のコンピューティングソリューションです。


Batch AIでInfinibandを利用して、Chainer MNのMNISTジョブを実行する

ここからは、以下のマイクロソフト社のBatch AI開発チームが作成しているGithubレポジトリを参考に、ジョブを実行していきます。前稿と同じく、AzureポータルのCloud Shellから実行します。

https://github.com/Azure/BatchAI/tree/master/recipes/Chainer/Chainer-GPU-Distributed-Infiniband

途中までは前回と同じ作業になります。


リソースグループとワークスペースの作成

az group create -n batchai.recipes -l eastus

az batchai workspace create -g batchai.recipes -n recipe_workspace -l eastus

*各コマンド(az batchai ***)の詳細なオプションの説明

https://docs.microsoft.com/en-us/cli/azure/batchai?view=azure-cli-latest


ストレージの準備

*データやアウトプット先をAzure Filesにしてしまうと、せっかくInfinibandで高速化してもストレージがネックになってしまうので、BlobまたはNFSなど別のオプションにしましょう。

こちらも前回と同じように準備します。ただし、今回は後から使うjobprep.shというスクリプトをtrain_mnist.pyと一緒にダウンロード、アップロードしておきます。

az storage account create -n <storage account name> --sku Standard_LRS -g batchai.recipes -l eastus

az storage container create -n scripts --account-name <storage account name>
az storage container create -n result --account-name <storage account name>
az storage share create -n logs --account-name <storage account name>

wget https://raw.githubusercontent.com/chainer/chainermn/v1.3.0/examples/mnist/train_mnist.py
wget https://raw.githubusercontent.com/Azure/BatchAI/master/recipes/Chainer/Chainer-GPU-Distributed-Infiniband/jobprep.sh
az storage blob upload -f train_mnist.py -n chainer/train_mnist.py --account-name <storage account name> --container scripts
az storage blob upload -f jobprep.sh -n chainer/jobprep.sh --account-name <storage account name> --container scripts


クラスターの作成とジョブの投入

クラスターの作成も流れは前回と同じですが、今回はInfinibandが付いているNC24Rシリーズを選択します。(Azureでは、仮想マシンのシリーズ名の最後にRが付いているものがInfiniband付きになります。今回はTesla K80が4枚載った、Infiniband付きシリーズのNC24Rにしていますが、例えばP100/V100のNC24R v2/v3)を利用することでより高速に実行できます。


注意点

Batch AIのデフォルトのクオータ(リソース制限)ではNCシリーズの仮想コアの上限値は24コアのため、NC24Rを2台(48仮想コア)並べようとするとエラーになります。サポートリクエストを上げて、クオータを上げて貰う必要があります。

クラスターを作成します。

az batchai cluster create -n nc24r -g batchai.recipes -w recipe_workspace -s Standard_NC24r -t 2 --generate-ssh-keys 

前回と同じく、ジョブ管理の箱であるExperimentを作成します。

az batchai experiment create -g batchai.recipes -w recipe_workspace -n chainer_experiment

次にカレントディレクトリにjob.jsonを以下のように作成します。いくつか前回(OpenMPIを利用)とは異なる箇所があります。


  1. コンテナー:今回は開発チームが作成したInfiniband用のIntel MPIを使う準備をしているコンテナーを利用します。

  2. --comnunicator:Intel MPIはcuda awareでないため、non_cuda_awareオプションを利用します。

  3. jobPreparationオプション:jobPraparationはコンテナー内で、コード(ここではtrain_mnist.py)を実行する前に流すスクリプトを設定するオプションです。ここでは、jobprep.shを流し、Intel MPIをインストールしています。

< >は適宜変更してください。

{

"$schema": "https://raw.githubusercontent.com/Azure/BatchAI/master/schemas/2018-05-01/job.json",
"properties": {
"nodeCount": 2,
"chainerSettings": {
"pythonScriptFilePath": "$AZ_BATCHAI_JOB_MOUNT_ROOT/scripts/chainer/train_mnist.py",
"commandLineArgs": "-g --communicator non_cuda_aware -o $AZ_BATCHAI_OUTPUT_MODEL",
"processCount": 8
},
"jobPreparation": {
"commandLine": "bash $AZ_BATCHAI_JOB_MOUNT_ROOT/scripts/chainer/jobprep.sh"
},
"stdOutErrPathPrefix": "$AZ_BATCHAI_JOB_MOUNT_ROOT/logs",
"mountVolumes": {
"azureFileShares": [
{
"azureFileUrl": "https://<AZURE_BATCHAI_STORAGE_ACCOUNT>.file.core.windows.net/logs",
"relativeMountPath": "logs"
}
],
"azureBlobFileSystems" :[
{
"accountName": "<Storage Account Name>",
"containerName": "scripts",
"credentials": {
"accountKey": "<Storage Account Key>"
},
"relativeMountPath": "scripts"
},
{
"accountName": "<Storage Account Name>",
"containerName":"result",
"credentials": {
"accountKey": "<Storage Account Key>"
},
"relativeMountPath": "result"
}
]
},
"outputDirectories": [{
"id": "MODEL",
"pathPrefix": "$AZ_BATCHAI_JOB_MOUNT_ROOT/result"
}],
"containerSettings": {
"imageSourceRegistry": {
"image": "batchaitraining/chainermn:IntelMPI"
}
}
}
}

あとは、前回と同じくジョブを実行します。

az batchai job create -n distributed_chainer_ib -c nc24r -g batchai.recipes -w recipe_workspace -e chainer_experiment -f job.json --storage-account-name <storage account name>

結果をポータルから確認します。無事ジョブが終了しました!


リソースのお片付けも忘れずに!

前項と同じですが。。。


クラスターのノード関係

・クラスターのノード数を減らす(0ノードにする)

az batchai cluster resize -n nc6 -g batchai.recipes -w recipe_workspace -t 0

・クラスターを削除する

az batchai cluster delete -n nc6 -g batchai.recipes -w recipe_workspace

・クラスターを自動スケールする(最小0ノード、最大10ノードの例)

az batchai cluster auto-scale -n nc6 -g batchai.recipes -w recipe_workspace --min 0 --max 10


リソースグループごと削除する

すべて削除する場合は、リソースグループごと削除します。

az group delete -n batchai.recipes -y


(おまけ)Intel MPIのベンチマークをノードに入って実行してみます!

実際にBatch AIのノードに入って、コンテナー上からIntel MPIのベンチマークを実行してみます。


補足:Batch AIのネットワークについて

Azureの仮想マシンは、すべて仮想ネットワークという閉じたネットワークに属すようデプロイされます。Batch AIは仮想マシン(仮想マシンスケールセット)がデプロイされる部分が隠蔽されていますが、このことには変わりはありません。ユーザーが作成した仮想ネットワーク(正確にはサブネット)にBatch AIのクラスターをデプロイすることもできますが、通常は10.0.0.0/*の仮想ネットワーク(サブネット)にデプロイされ、10.0.0.4から順番にプライベートIPが割り振られます。そしてDockerは--net=hostで起動されているため、ホストのネットワークインターフェースを共有します。

また、外部からアクセスする際は、パブリックIPを持ったロードバランサー経由(ポート転送)でSSHでアクセスすることになります。

SSHで外部からアクセスするために、ロードバランサーのIPアドレスとポート転送しているポートを調べます。

az batchai cluster node list -c nc24r -g batchai.recipes -w recipe_workspace

そしてそのIPとポート番号でSSHします。

Dockerが動いていることを確認し、中に入ります。

そして、Intel MPIのベンチマーク、pingpongをInfiniband上で流してみます。

ちなみに、Infinibandを使わないで同じベンチマークを流すと以下のようになります。

レイテンシーは数十倍、バンド幅も10倍以上変わってくるのが見えますね。

今回はMNISTでかつ2ノードなので、Open MPI版と大きく結果が変わらないかもしれませんが、ノード数が増え、かつ通信量が大きくなるようなジョブの場合、速度が全く変わってきます。

以上、今回はChainer MNをBatch AIを使って、簡単にInfinibandとGPUを使って高速・並列に実行してみました。


参考資料

(公式)Azure Document

https://docs.microsoft.com/ja-jp/azure/batch-ai/

(公式)Github Batch AI

https://github.com/Azure/BatchAI

*ドキュメントよりもGithubのほうが内容が充実しており、各フレームワークのレシピ(例)が揃っています。

(手前味噌ですが)Deep Learning Lab MeetUp (2018年6月27日) 学習編資料

https://www.slideshare.net/ssuser147cbc/deep-learning-lab-meetup-azurebatch-ai

*本稿は、個人の見解に基づいた内容であり、所属する会社の公式見解ではありません。また、いかなる保証を与えるものでもありません。正式な情報は、各製品の販売元にご確認ください。