メインコンテンツまでスキップ

HorovodRunner:Horovodによる分散ディープラーニング

important

Horovod と HorovodRunner は非推奨になりました。 15.4 LTS ML より後のリリースには、このパッケージはプリインストールされません。 分散ディープラーニングの場合、Databricks では、PyTorch による分散トレーニングに TorchDistributor を使用するか、TensorFlow による分散トレーニングに tf.distribute.Strategy API を使用することをお勧めします。

HorovodRunner を使用して機械学習モデルの分散トレーニングを実行し、Databricks で Horovod トレーニング ジョブを Spark ジョブとして起動する方法について説明します。

HorovodRunnerとは何ですか?

HorovodRunner は、 Horovod フレームワークを使用して Databricks 上で分散ディープラーニングワークロードを実行するための汎用 API です。 Horovod を Spark の バリアモードと統合することで、Databricks は Spark で長時間実行されるディープラーニングトレーニングジョブの安定性を高めることができます。 HorovodRunnerは、Python フックを持つディープラーニング トレーニング コードを含むHorovod メソッドを取ります。HorovodRunner は、メソッドをドライバーにピクルス化し、Spark ワーカーに配布します。 Horovod MPI ジョブは、バリア実行モードを使用して Spark ジョブとして埋め込まれます。 最初のエグゼキューターは、BarrierTaskContextを使用してすべてのタスクエグゼキューターのIPアドレスを収集し、mpirunを使用して Horovod ジョブをトリガーします。 各Python MPIプロセスは、pickle化されたユーザープログラムをロードし、逆シリアル化して実行します。

HorovodRunner

HorovodRunner による分散トレーニング

HorovodRunner を使用すると、Horovod トレーニング ジョブを Spark ジョブとして起動できます。 HorovodRunner API は、表に示されているメソッドをサポートしています。 詳細については、 HorovodRunner API のドキュメントを参照してください。

メソッドとシグネチャー

説明

init(self, np)

HorovodRunnerのインスタンスを作成します。

**run(self, main, **kwargs)**

main(**kwargs)を呼び出す Horovod トレーニング ジョブを実行します。main 関数とキーワード引数は cloudpickle を使用してシリアル化され、クラスター ワーカーに配布されます。

HorovodRunner を使用して分散トレーニング プログラムを開発する一般的なアプローチは次のとおりです。

  1. ノード数で初期化された HorovodRunner インスタンスを作成します。
  2. Horovod の使用方法で説明されている方法に従って Horovod トレーニング方法を定義し、メソッド内にインポートステートメントを追加してください。
  3. トレーニング方法を HorovodRunner インスタンスに渡します。

例えば:

Python
hr = HorovodRunner(np=2)

def train():
import tensorflow as tf
hvd.init()

hr.run(train)

ドライバーで HorovodRunner を n サブプロセスのみで実行するには、 hr = HorovodRunner(np=-n)を使用します。 たとえば、ドライバー ノードに 4 つの GPU がある場合、最大 4``n を選択できます。パラメーター npの詳細については、 HorovodRunner API のドキュメントを参照してください。 サブプロセスごとに 1 つの GPU をピン留めする方法の詳細については、 Horovod 使用ガイドを参照してください。

よくあるエラーは、TensorFlow オブジェクトが見つからない、またはピクルス化できないというものです。 これは、ライブラリのインポートステートメントが他のエグゼキューターに配布されていない場合に発生します。 この問題を回避するには、すべてのインポートステートメント ( import tensorflow as tfなど) を Horovod トレーニングメソッドの先頭と、Horovod トレーニングメソッドで呼び出される他のユーザー定義関数 の両方に 含めます。

Horovod TimelineでHorovodのトレーニングを録画

Horovodには、 Horovod Timelineと呼ばれる、その活動のタイムラインを記録する機能があります。

important

Horovod Timeline は、パフォーマンスに大きな影響を与えます。 Inception3 のスループットは、Horovod Timeline を有効にすると ~40% 低下する可能性があります。 HorovodRunner ジョブを高速化するには、Horovod Timeline を使用しないでください。

トレーニングの進行中は、Horovodタイムラインを表示することはできません。

Horovod Timeline を記録するには、 HOROVOD_TIMELINE 環境変数をタイムライン ファイルを保存する場所に設定します。 Databricks では、タイムライン ファイルを簡単に取得できるように、共有ストレージ上の場所を使用することをお勧めします。 たとえば、次のようにDBFSローカル ファイル APIsを使用できます。

Python
timeline_dir = "/dbfs/ml/horovod-timeline/%s" % uuid.uuid4()
os.makedirs(timeline_dir)
os.environ['HOROVOD_TIMELINE'] = timeline_dir + "/horovod_timeline.json"
hr = HorovodRunner(np=4)
hr.run(run_training_horovod, params=params)

次に、トレーニング関数の先頭と末尾にタイムライン固有のコードを追加します。 次のサンプル ノートブックには、トレーニングの進行状況を表示するための回避策として使用できるサンプル コードが含まれています。

Horovodタイムラインサンプルノートブック

Open notebook in new tab

タイムライン ファイルをダウンロードするには、 Databricks CLI を使用し、Chrome ブラウザーの chrome://tracing 機能を使用して表示します。 例えば:

Horovodのタイムライン

開発ワークフロー

これらは、単一ノードのディープラーニング コードを分散トレーニングに移行するための一般的な手順です。 このセクションの「例: HorovodRunnerを使用して分散ディープラーニングに移行する」では、これらの手順を説明しています。

  1. 単一ノードコードを準備します。 TensorFlow、Keras、または PyTorch を使用してシングルノードコードを準備してテストします。

  2. HorovodRunnerへの移行: 「Horovod の使用法」の指示に従って、 Horovod を使用してコードを移行し、ドライバーでテストします。

    1. Horovodを初期化するための hvd.init() を追加します。
    2. このプロセスで使用するサーバー GPU を config.gpu_options.visible_device_listを使用してピン留めします。 プロセスごとに 1 つの GPU の一般的なセットアップでは、これをローカル ランクに設定できます。 その場合、サーバー上の最初のプロセスに最初のGPUが割り当てられ、2番目のプロセスには2番目のGPUが割り当てられます。
    3. データセットのシャードを含めます。 このデータセット演算子は、各ワーカーが一意のサブセットを読み取ることができるため、分散トレーニングを実行するときに非常に便利です。
    4. ワーカーの数によって学習率をスケーリングします。 同期分散トレーニングの有効なバッチ サイズは、ワーカーの数によってスケーリングされます。 学習率を上げると、バッチサイズの増加が補われます。
    5. オプティマイザを hvd.DistributedOptimizerで包みます。 分散オプティマイザは、勾配計算を元のオプティマイザに委任し、allreduce または allgather を使用して勾配を平均化し、平均化された勾配を適用します。
    6. hvd.BroadcastGlobalVariablesHook(0)を追加して、ランク 0 から他のすべてのプロセスに初期変数の状態をブロードキャストします。これは、トレーニングがランダムな重みで開始されるとき、またはチェックポイントから復元されるときに、すべてのワーカーの一貫した初期化を確保するために必要です。 または、 MonitoredTrainingSessionを使用していない場合は、グローバル変数が初期化された後に hvd.broadcast_global_variables 操作を実行できます。
    7. チェックポイントをワーカー 0 にのみ保存するようにコードを変更して、他のワーカーがチェックポイントを破損しないようにします。
  3. HorovodRunnerへの移行: HorovodRunner は、Python 関数を呼び出すことによって Horovod トレーニングジョブを実行します。 メインのトレーニング手順を 1 つの Python 関数にラップする必要があります。 その後、HorovodRunner をローカル モードと分散モードでテストできます。

ディープラーニングライブラリを更新する

TensorFlow、Keras、または PyTorch をアップグレードまたはダウングレードする場合は、新しくインストールしたライブラリに対してコンパイルされるように Horovod を再インストールする必要があります。 たとえば、TensorFlowをアップグレードする場合、DatabricksTensorFlowのインストール手順のinitスクリプトを使用し、その末尾に次のTensorFlow固有のHorovodインストールコードを追加することをお勧めします。Horovodのインストール手順を参照して、PyTorchやその他のライブラリのアップグレードやダウングレードなど、さまざまな組み合わせで作業します。

Bash
add-apt-repository -y ppa:ubuntu-toolchain-r/test
apt update

# Using the same compiler that TensorFlow was built to compile Horovod
apt install g++-7 -y
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60

HOROVOD_GPU_ALLREDUCE=NCCL HOROVOD_CUDA_HOME=/usr/local/cuda pip install horovod==0.18.1 --force-reinstall --no-deps --no-cache-dir

例: HorovodRunner を使用した分散型ディープラーニングへの移行

次の例は、 MNIST データセットに基づいており、単一ノードのディープラーニング プログラムを HorovodRunnerを使用して分散ディープラーニングに移行する方法を示しています。

制限

  • ワークスペース ファイルを操作する場合、 np が 1 より大きい値に設定され、ノートブックが他の相対ファイルからインポートされると、HorovodRunner は機能しません。 HorovodRunnerの代わりに Horovod.spark を使用することを検討してください。
  • WARNING: Open MPI accepted a TCP connection from what appears to be a another Open MPI process but cannot find a corresponding process entry for that peerのようなエラーが発生した場合は、クラスター内のノード間のネットワーク通信に問題があることを示しています。このエラーを解決するには、トレーニング コードに次のスニペットを追加して、プライマリ ネットワーク インターフェイスを使用します。
Python
import os
os.environ["OMPI_MCA_btl_tcp_if_include"]="eth0"
os.environ["NCCL_SOCKET_IFNAME"]="eth0"