LoginSignup
0
0

More than 1 year has passed since last update.

DatabricksにおけるHorovodRunnerの活用:Horovodによる分散ディープラーニング

Last updated at Posted at 2022-09-09

HorovodRunner: distributed deep learning with Horovod | Databricks on AWS [2022/8/17時点]の翻訳です。

本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。

HorovodRunnerは、Horovodフレームワークを用いたDatabricks上で分散ディープラーニングワークロードを実行するための汎用APIです。HorovodとSparkのバリアーモードを組み合わせることで、DatabricksのSparkで長時間稼働するディープラーニングトレーニングジョブに対して高い安定性を提供できるようになります。HorovodRunnerはディープラーニングトレーニングのコードとHorovodのフックを含むPythonメソッドを受け取ります。HorovodRunnerはそのメソッドをドライバー上でpickleし、Sparkワーカーに分散させます。HorovodのMPIジョブは、バリアー実行モードを用いてSparkジョブとして埋め込まれます。最初のエグゼキューターがBarrierTaskContextを用いて全てのタスクエグゼキューターのIPアドレスを収集し、mpirunを用いてHorovodのジョブを起動します。それぞれのPython MPIプロセスは、pickleされたユーザープログラムをロードし、デシリアライズして実行します。

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

HorovodRunnerを用いることで、HorovodトレーニングジョブをSparkジョブとして起動することができます。HorovodRunnerのAPIは以下のテーブルのメソッドをサポートしています。詳細は、HorovodRunner API documentationをご覧ください。

メソッドとシグネチャ 説明
init(self, np) HorovodRunnerのインスタンスを作成します。
run(self, main, **kwargs) main(**kwargs)を呼び出すことでHorovodトレーニングジョブを実行します。cloudpickleを用いてmain関数とキーワードの引数はシリアライズされ、クラスターのワーカーに分散されます。

HorovodRunnerを用いた分散トレーニングプログラムを開発する一般的なアプローチは以下の通りとなります。

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

例は以下のようになります。

Python
hr = HorovodRunner(np=2)

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

hr.run(train)

n個のサブプロセスを持つドライバーでのみHorovodRunnerを実行するには、hr = HorovodRunner(np=-n)を使用します。例えば、ドライバーのーどに4GPUがある場合、最大4までnを指定することができます。パラメーターnpの詳細については、HorovodRunner API documentationをご覧ください。サブプロセスに一つのGPUを固定する方法に関しては、Horovod usage guideをご覧ください。

よくあるエラーは、TensorFlowオブジェクトが見つからない、pickleされないというものです。これは、ライブラリのimport文が他のエグゼキューターに分散されていない場合に生じます。この問題を回避するには、全てのimport文(例えば、import tensorflow as tf)をHorovodのトレーニングメソッドと、Horovodトレーニングメソッドで呼び出されるその他の全てのユーザー定義関数の両方に含めるようにしてください。

Horovod TimelineによるHorovodトレーニングの記録

Horovodには、Horovod Timelineと呼ばれる自分のアクティビティを記録する機能が備わっています。

重要!
Horovod Timelineはパフォーマンスに多大なる影響を及ぼします。Horovod Timelineを有効化すると、Inception3のスループットが~40%減少することがあります。HorovodRunnerを高速化したい場合には、Horovod Timelineを使わないでください。

トレーニングが進行中の状態でHorovod Timelineを参照することはできません。

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

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 Timelineのサンプルノートブック

タイムラインファイルをダウンロードするには、Databricks CLIFileStoreを使用し、参照するには以下のようにChromeブラウザのchrome://tracing機能を使用します。

開発のワークフロー

シングルノードのディープラーニングのコードを分散トレーニングに移行するための一般的なステップが存在します。このセクションのサンプルでは、これらのステップを説明しています。

  1. シングルノードのコードを準備する: TensorFlow、Keras、PyTorchを用いたシングルノードのコードを準備し、テストします。

  2. Horovodに移行する: Horovodを用いたコードに移行し、ドライバー上でテストするためにHorovod usageの手順に従います。

    1. Horovodを初期化するためにhvd.init()を追加します。
    2. config.gpu_options.visible_device_listを用いてこのプロセスで使用されるサーバーGPUをピン留めします。プロセスごとに1つのGPUを用いる典型的なセットアップを行うと、これはローカルのランクに設定されます。この場合、サーバーの最初のプロセスには最初のGPUが割り当てられ、2番目のプロセスには2番目のGPUが割り当てられ、以降も同様となります。
    3. データセットのシャードを含めます。データセットオペレーターを用いることで、それぞれのワーカーがユニークなサブセットを読み込めるようになるので、分散トレーニングの実行においては非常に有用です。
    4. ワーカーの数で学習率をスケールさせます。ワーカーの数で、同期分散トレーニングの効率的なバッチサイズをスケールさせることができます。学習率の増加は、バッチサイズの増加を埋め合わせることになります。
    5. hvd.DistributedOptimizerでオプティマイザーをラッピングします。分散オプティマイザーは、オリジナルのオプティマイザーに徐々に計算処理を移譲し、allreduceやallgatherを用いて勾配を平均し、平均された勾配を適用します。
    6. ランク0から他のプロセスに初期変数の状態をブロードキャストするために、hvd.BroadcastGlobalVariablesHook(0)を追加します。トレーニングがランダムな重みからスタートしたり、チェックポイントから復旧した際に全てのワーカーで一貫性のある初期化が行われるようにするためにはこれが必要となります。あるいは、MonitoredTrainingSessionを使用している場合には、グローバル変数が初期化された後にhvd.broadcast_global_variablesオペレーションを実行することができます。
    7. 他のワーカーの挙動を破壊しないようにするために、ワーカー0でのみチェックポイントを保存するようにコードを変更します。
  3. HorovodRunnerに移行する: HorovodRunnerはPython関数を呼び出すことでHorovodトレーニングジョブを実行します。メインのトレーニング処理を単一のPython関数でラップする必要があります。そして、ローカルモードでHorovodRunnerをテストしてから、分散モードでテストすることができます。

ディープラーニングライブラリのアップデート

注意
本書にはDatabricksでは使用しないslaveという単語への参照が含まれています。ソフトウェアからこの単語が削除された場合には、本書からも削除します。

TensorFlow、Keras、PyTorchをアップグレード、ダウングレードする際は、新たにインストールしたライブラリを用いてコンパイルしたHorovodを再インストールす必要があります。例えば、Tensorflowをアップグレードしたい場合、TensorFlow installation instructionsにあるinitスクリプトを使用し、最後に以下のTensorFlow固有のHorovodインストールコードを追加することをお勧めします。PyTorchなどのライブラリのアップグレード、ダウングレードのような異なる組み合わせに関しては、Horovod installation instructionsをご覧ください。

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 --slave /usr/bin/g++ g++ /usr/bin/g++-7

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

サンプル

MNISTデータセットを用いた以下のサンプルでは、シングルノードのディープラーニングプログラムを、HorovodRunnerを用いてどのように分散ディープラーニングに移行するのかをデモしています。

制限

  • ワークスペースでReposのファイルサポートが有効化されており、npが1より大きい値に設定され、ノートブックがRepoにあるファイルからimportしている場合、HorovodRunnerは動作しません。HorovodRunnerではなくhorovod.sparkを使用することを検討してください。

Databricks 無料トライアル

Databricks 無料トライアル

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0