CCCMKホールディングス TECH Labの Tech Blog

TECH Labスタッフによる格闘記録やマーケティング界隈についての記事など

分散学習をすると本当に処理時間が速くなるのか、LT用に確かめてみました。

こんにちは、技術開発の三浦です。

最近とても寒い日が続いています。毎年この時期になると手にあかぎれができてしまうので、今年はちょっと外に出る場合も手袋をするように心がけるようにしました。今のところあかぎれはできていないのですが、だんだんできてきそうな感じがしてきたので、ハンドクリームも使うようにしようかな、と考えています。

先日databricksに関するイベントでLT(ライトニングトーク)の機会があり、今回の記事はそのLT用に準備した、最近ちょっと気になっていたことを調べた話をご紹介しようと思います。

調べたこと

私のLTのタイトルは、こちらです。

LTのタイトル

Databricksを使い、Spark上で深層学習の分散学習をする機会が増えてきたのですが、それによって学習が速くなることがある一方で、むしろ遅くなっていることもあるのでは、と感じることがありました。そこでどのようなケースで分散学習が有効になるのかを、一度調べておきたいな、ということで上の様なテーマを設定し、ちょっと時間を取って実験をしてみました。

試したこと

下の図のような構成でクラスタを作りました。それぞれのノードには利用可能なGPUが2台ずつ搭載されています。また、DriverノードもWorkerノードも同じサイズのVMで構成しています。

クラスタおよび分散学習の構成

そして以下のそれぞれの場合で同じ量のデータセットで10epoch学習をし、1epochに平均どれくらいの時間を有したのかを記録し、比較します。本当はクラスタの起動にかかる時間やそれぞれの場合の精度も比較しようと考えたのですが、今回は1epochの処理時間のみに焦点を絞っています。

  • DriverノードでGPUx2(np=-2)
  • Workerノード1台でGPUx2(np=2)
  • Workerノード2台でGPUx2(np=4)
  • Workerノード3台でGPUx2(np=6)

これらのパターンの切り替えは、Driverノードで実行するHorovodRunner()の引数npを変更して行います。上のリストのカッコ内で指定した値でHorovodRunner()をそれぞれ実行します。

また実験に使用したデータセットはCIFAR-10データセットの学習用データ5万件です。このうち90%を学習用、10%を検証用として各epochの最後に検証データによる精度測定のフェーズを挟んでいます。

また、

  • Batch-Sizeは64にしました。
  • ベースモデルは事前学習済みの”ResNet-50”を使用しました。
  • learning rateはcyclical learning rateで探索したものを固定して使用しました。

といった点をその他の前提条件としています。

結果は?

結果は以下のようになりました。

1epochの平均処理速度の比較

なんと、圧倒的に処理速度が速いのがDriverノードだけで実行した場合でした。何か分散学習の指定を間違えたかな・・・と思いHorovodのこちらのPyTorch-Lightningで使用する場合の使い方などを調べてみたのですが、特に問題は無さそうです。

np=-2の場合を除けば、npの値が増えれば増えるほど処理速度は上がっているので、決定的なのはDriverノードで実行するか、Workerノードで分散させるか、という点のようです。

原因は?

Sparkによる要因、Horovodによる要因が相互に関係していそうで切り分けが難しいのですが、恐らくDriverノードとWorkerノード間の通信など、Driverノードだけで完結する場合には発生しない処理があり、それが処理時間を遅くしている要因だと考えました。今回のCIFAR-10データセットのような小さなサイズの画像(32x32x3)で、かつBatch-Sizeが64というかなり小さなサイズの場合、分散学習によって得られるメリットが小さく、むしろ追加の通信処理によるデメリットの方が目立ってしまった。そんなところが今回の結果の原因として考えられそうです。

そこでBatch-Sizeを大きくし、1Stepで扱うデータのサイズが大きくなった場合に処理時間の違いがどうなるか、最後に調べてみました。Batch-Sizeが大きくなればなるほど、データを分割して処理できる分散学習の強みが発揮できると考えられるからです。

結果です!

Batch-Sizeを64, 256, 512にして同じように1epochの平均処理時間を比較してみました。

Batch-Sizeも変えて比較した結果

Batch-Sizeが大きくなると、1epochにかかる時間は全ての場合で速くなっていきます。しかしnp=-2よりもnp=6の方がその傾向がより顕著で、Batch-Sizeが512になるとついにnp=6の処理時間が最も速い結果になりました。

やはり1stepで扱うデータサイズが大きくなると、Workerノードを使って分散学習をさせるメリットが目立つようになるようです。

まとめ

ということで、今回はライトニングトーク用に試してみたちょっとした実験の話をご紹介させて頂きました。512のBatch-Sizeでやっと違いが出るのか・・・と思った一方、普段実務で縦横32のサイズの画像を扱うことはあまりなく、256サイズぐらいを使うことが多いのですが、この場合だとBatch-Size10程度で縦横32の画像のBatch-Size512のデータ量を上回ります。ですので今回の実験の結果によれば、概ね普段の用途においてはWorkerノードで6プロセス程度の分散学習を行えば、Driverノードで実行するよりも処理時間を速くすることが出来ると言えそうです(もちろん複数ノードを立ち上げることによるコストは考慮する必要があります!)。

あとは今回対象にしなかったクラスタの起動時間もしっかり調べておきたいなと考えています。しかし普段何となく気になっていたことを今回調べることが出来てよかったと思いました。