MXNet How To : MXNet をデータ並列で複数の CPU/GPU で実行する

MXNet How To : MXNet をデータ並列で複数の CPU/GPU で実行する (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
日時 : 02/28/2017

* 本ページは、MXNet 本家サイトの “Run MXNet on Multiple CPU/GPUs with Data Parallel” を翻訳した上で
適宜、補足説明したものです:
    http://mxnet.io/how_to/multi_devices.html

How to train with multiple CPU/GPUs with data parallelism – 複数の GPU を使用するための MXNet のデフォルトを提供します。そしてまた、(GPU の数と個々の GPU 負荷のような)GPU データ並列性設定をカスタマイズし、複数の GPU でトレーニングし、GPU 接続オプションを設定し、GPU 間でディレクトリを同期し、ネットワークインターフェイスを選択し、そして接続をデバッグするための説明とコマンドも提供します。

 

MXNet は、異なる物理マシン上に位置するかもしれない、複数の CPU と GPU でのトレーニングをサポートします。

 

データ並列性 vs モデル並列性

デフォルトでは、MXNet は複数のデバイスに渡り負荷を分割するデータ並列性を使用します。n デバイスがあると仮定すると、各々の一つは完全なモデルを得てそれをデータの 1/n 上でトレーニングします。勾配や更新されたモデルのような結果はこれらのデバイスで交差して通信されます。

モデル並列性もまたサポートされます。この並列性では各デバイスはモデルの一部を維持します。モデルが単一のデバイスにフィットしないほど巨大な時に有用です。多層 LSTM モデルのためにモデル並列性をどのように行なうかを示す チュートリアル があります。
このチュートリアルではデータ並列性に焦点を当てます。

 

単一マシン内の複数 GPU

作業負荷分割

デフォルトでは、MXNet はデータバッチを各 GPU に均等に分割します。バッチサイズ b と k GPU を仮定すると、一つの iteration で各 GPU は b/k サンプル上で forward と backward を実行します。勾配は、モデルを更新する前に全ての GPU に渡り加算されます。

どのように使用するか

マシンが一つまたはそれ以上のインストールされた GPU カードを持つならば、各カードは 0 から始まる数字でラベル付けされます。特定の GPU を使用するためには、コードで context ctx を指定することもできますし、コマンドラインで –gpus を渡すこともできます。例えば、python で GPU 0 と 2 を使用するためにはしばしか以下で model を作成できます :

import mxnet as mx
model = mx.model.FeedForward(ctx=[mx.gpu(0), mx.gpu(2)], ...)

一方で example/image-classification のようにプログラムが –gpus フラグを受け取るならば、次のように試すことができます :

python train_mnist.py --gpus 0,2 ...

進んだ使い方

GPU が異なる計算パワーを持つ場合には、それらのパワーに従って負荷を分割できます。例えば、GPU 0 が GPU 2 よりも3倍速いのであれば、追加の負荷オプション work_load_list=[3, 1] を提供します、より詳細は model.fit を参照してください。

複数 GPU でのトレーニングは、もし全ての他のハイパー・パラメータが同じであるならば単一のGPU と同じ結果になるべきです。しかし実際には、主として I/O のランダムネス (ランダムな順序あるいは他の拡張)、異なる seed での重みの初期化、そして CUDNN によって様々になります。

どこで勾配が集約されるかを、実行されるならばモデル更新を異なる KVStore を作成することで制御することができます。これはデータ通信のためのモジュールです。インスタンスを得るために mx.kvstore.create(type) を使用するかプログラム・フラグ –kv-store type を使用することができます。

2つの一般的に使用されるタイプがあります :

  • local: 全ての勾配が CPU メモリにコピーされて重みはそこで更新されます。
  • device: 勾配の集約も重み更新も両者とも GPU 上で実行されます。また GPU peer-to-peer 通信の使用を試みます、これは潜在的には通信を加速します。しかしこのオプションはより高い GPU メモリ使用量という結果になるかもしれません。

多くの数の GPU, e.g. >-4 があるのであれば、より良いパフォーマンスのために device を使用することを提案します。

 

複数マシンでの分散トレーニング

複数のマシンで実行するために KVStore タイプを単純に変更することができます。

  • dist_sync は local と同様に振る舞います。 しかし一つの主要な違いは batch-size がここでは各マシンで使用される batch サイズを意味することです。従って n マシンがあり batch サイズ b を使用するのであれば、dist_sync は batch サイズ n*b の local と同等の振る舞いをします。
  • dist_device_sync は device vs local と類似の差異を別にすれば dist_sync と同一です。
  • dist_async は非同期な更新を実行します。ひとたび任意のマシンから勾配を受けとれば重みが更新されます。更新は atomic で、すなわち、同じ重みについて同時には2つの更新は起きません。けれども、順序は保証されません。

どのようにジョブを launch するか

分散ジョブを launch するのは単一のマシン上で実行するのとは少し異なります。MXNet は ssh, mpi, sge, あるいは yarn を使用してジョブを開始するために tools/launch.py を提供しています。

ディレクトリ mxnet/example/image-classification で train_mnist.py を使用して mnist を lenet でトレーニングすることを望むと仮定します。単一のマシン上では次のように実行できます :

python train_mnist.py --network lenet

さて2つの ssh-able マシンがありこれらの2つのマシン上でそれをトレーニングしたいとします。まず、これら2つのマシンの IP (or ホスト名) を hosts ファイルに保存します、e.g.

$ cat hosts
172.30.0.172
172.30.0.171

次に、mxnet フォルダが両方のマシンから e.g. network filesystem 上でアクセス可能であれば、次で実行できます :

../../tools/launch.py -n 2 --launcher ssh -H hosts python train_mnist.py --network lenet --kv-store dist_sync

単一マシンの引数の他に、次を使用することに注意してください :

  • ジョブを submit するために launch.py を使用する
  • launcher を提供します、全てのマシンが ssh-able ならば ssh、mpirun が利用可能であれば mpi、Sun Grid Engine のためには sge、そして Apache Yarn のためには yarn。
  • -n 実行するワーカー・ノードの数
  • -H ssh と mpi で必要なホストファイル
  • –kv-store は dis_sync or dist_sync を使用

ディレクトリを同期する

mxnet フォルダがアクセス可能でないとして考えます。最初に MXNet ライブラリをこのフォルダに以下でコピーします

cp -r ../../python/mxnet .
cp -r ../../lib/libmxnet.so mxnet

そして現在のディレクトリを全てのマシンの /tmp/mxnet ディレクトリに同期するように –sync-dst-dir で launch.py に依頼します :

../../tools/launch.py -n 2 -H hosts --sync-dst-dir /tmp/mxnet \
   python train_mnist.py --network lenet --kv-store dist_sync

特定のネットワーク・インターフェイスを使用する

MXNet は最初の利用可能なネットワーク・インターフェイスをしばしば選択します。しかし複数のインターフェイスを持つマシンに対して、環境変数 DMLC_INTERFACE でデータ通信のためにどのネットワーク・インターフェイスを使用するかを指定できます。例えば、eth0 を使用するためには :

export DMLC_INTERFACE=eth0; ../../tools/launch.py ...

デバッグ接続

デバッグ・ロギングを見るためには PS_VERBOSE=1 をセットします、e.g.

export PS_VERBOSE=1; ../../tools/launch.py ...

More

  • See more launch options by ../../tools/launch.py -h
  • See more options of ps-lite
 

以上