MN-2が動き出しました

土井 裕介

2019-06-26 18:11:02

先日リリースさせて頂いたとおり,MN-2の構築を行っています.MN-2は最新世代の,1024基のNVIDIA(R) V100 GPUが計算力の主力となります.現在利用しているMN-1およびMN-1bにおいて1024基のP100と512基のV100を稼動させていますが,MN-2の追加によりGPU数換算で合計2560基となり,保有計算力を大幅に強化しました.とはいえ,現時点ではKubernetesをはじめとしたソフトウェアサービススタックのセットアップ中であり,GPUは主にベンチマークを実施して状態確認を行っている段階です.

PFNでリサーチャをやっている,土井裕介です.最近はリサーチ業務はあまりやっておらず,社内インフラ関係の全体の世話役のような業務が主担当になっています.今回,物理構築が一段落したのでBlogにてMN-2の概要やポイントを紹介させて頂きます.

構築途中のMN-2

構築中のMN-2

なぜMN-2を作るのか?

よく,「なぜPFNは自前インフラを持つのか?」というご質問を頂きます.自前インフラを持つ理由にはいろいろな側面があって一言では説明できないのですが,土井としては一つ,ハードウェアの全コントロールを握りたいから,という理由があります.例えば,計算のパフォーマンスが出ないという時に,どこをどう改善すればいいか,改善するとしてどのようなアプローチが存在するかを考えます.このとき,実際のハードウェアが上から下まできちんと見えるか,それともクラウドのむこうにあるのかで,取ることができるアプローチの幅にかなりの差が生まれます.特に今回はネットワークも含めて全て自前となっているため,見ることができる計測点が増えており,深層学習に向けたインフラサイドの研究開発の基盤としても活用できると期待しています.

さらに,今後 MN-Coreを使った計算機クラスタ(MN-3)も予定しています.MN-Coreは少なくとも当面はクラウドには置けないので,これを活用するためには自前のインフラを持つ必要があります.電源・冷却・ネットワーク・ストレージを含めて共用する前提で,GPUクラスタ (MN-2) を事前に作ることで,MN-3の構築に必要な経験をPFN社内で貯めている,という側面もあります.

MN-2の設計のポイント

MN-2の設計にあたり,いろいろなことを考えました.考えたことの大半は実現性との兼ね合いや時間との戦いの中で没になりましたが,一部実現したポイントもあるので,かいつまんでご紹介させてください.

ラック設計・電源・冷却

今回採用したGPUサーバは,8GPUを1台に搭載しており,定格で1台あたり3.5kWの消費電力です.床の耐荷重や電源供給・排熱等の問題,またMN-3の先行モデルとしての役割もあり,1ラックあたりの搭載数は4ノードとしています.1ラックあたり4ノード32GPUで定格14kWという計算になります.今となってはこの熱密度は高い方ではありませんが,純粋な空冷設備としてはそれなりに高い部類に入ると思っています.MN-2ではこのGPU計算ラックを連続で16ラック並べたものを背面を対向として2列置いています.合計32ラック128ノードになります.

MN-2クラスタを置かせて頂いているJAMSTEC横浜研究所シミュレータ棟は,冷気が床下から吹き出して天井側から熱気を回収する構造になっています.MN-2のGPUの排熱が他のGPUや地球シミュレータに与える影響を最小限とするため,背面(熱風が出る側)を対向させ,ラックの両端にドアを設置して,熱気が横方向に流れないように閉じ込めています.上方は空けてあるので,下から来る冷気の勢いと対流効果で熱の大半は天井側に送られるデザインです.さらに,ラック背面にフィンを設置して熱風が対向のラックに回りこみにくいようにしています.

稼動中のMN-2 背面

GPUの排熱を上方に逸らす整流板をつけた状態

実際に全GPUに対して模擬的な負荷をかけて稼動させてみましたが,hot側の温度は高くなったものの,cold側の温度はほぼ影響なく,想定通りの結果となりました.

高負荷試験時の温度変化

高負荷試験時の温度変化 (下段: 吸気/COLD側 上段: 排気/HOT側)

ネットワークとインターコネクト

HPCにおいては,計算機を相互接続するインターコネクトは重要です.深層学習においても同じことが言えますが,例えばさまざまな種類の巨大なシミュレーションを連続的に分散実行するようなスーパーコンピュータのワークロードと,学習途中のパラメータを適時同期する深層学習のワークロードにおいては、求められる性質は異なります.深層学習において支配的なデータ通信は,主にデータセットのロードとパラメータ交換であり,パケットサイズがおおきくなり,バンド幅が重要になりがちな傾向があります.

PFNでは技術吟味の結果,ファイルシステムはいわゆるHPC向けのファイルシステムではなく,Hadoopなどで使われているHDFSをメインに利用して,ローカルのデータキャッシュを活用する方向で検討しています.このことから,データセットの読み込みはEthernetが中心となります。従来多く使われてきた(MN-1でも利用している)InfinibandとEthernetの両方で広帯域の確保はPCIeのレーン数の制約から難しい場合があります.また,InfinibandとEthernetの両方に投資することは機能的には二重投資となることもあり,MN-2では冒険的に,インターコネクトの役割も全面的にEthernetとして,RoCEv2(RDMA over Converged Ethernet)を採用しました.パフォーマンスは,一部のInfinibandが得意としているshort packetの領域を除き,Infinibandと遜色ないことを確認しています.

今後

MN-2としての本格稼動は7月を予定していますが,先行して現状のクラスタの概要を紹介しました.
今後MN-3の構築がはじまる見込みで,それにあわせてPFNではインフラ人材も募集中です.特に運用・改善の領域において,Kubernetes上で動作する深層学習のワークロードと,MN-Coreを含めた先端ハードウェアとを両方睨んで最適化を行う,というアツい仕事が待ってます.我こそは! という方は,是非弊社ホームページにある採用の欄からご連絡いただくか,個人的にご存知のPFN社員なり,土井 (doi@preferred.jp) までご連絡ください.

ローカル環境のコード差分をリモートで実行する際に再現性を担保できるコマンドラインツール「Git Ghost」公開

Daisuke Taniwaki

2019-05-13 08:00:37

概要

大村谷脇で開発したローカル環境のコード差分をリモートで実行する際に再現性を担保できるコマンドラインツールGit Ghostをオープンソースとして公開しました。このツールを使うことで、試行錯誤しながら実験をするフェーズにおいても、以前修正して実行したローカル環境のコードに簡単に戻ることができます。

開発の動機

機械学習のジョブを実行中に試行錯誤でさらに他のジョブを実行することはよくあります。Git Ghostを作る前では、そのための一番単純な方法として、例えば、ソースコードをgitで管理し、rsyncコマンドでローカル環境での差分をKubernetesクラスターに同期して機械学習ジョブを実行していました。その際、実行したプログラムが良い結果を出した場合に、以前に修正したコードに戻りたいことがよくありましたが、この方法では、gitでソースコードをバージョン管理していても、rsyncで同期したローカル環境での差分についてはバージョン管理がされていないため、以前のコードに戻ることは困難でした。

これに対処するための1つのアイデアとして、ローカル環境での修正を全てコミットしてリモートにプッシュすることがまず考えられます。しかし、たった数文字の変更のためにコミットしてプッシュするのは非常に面倒であり、リモートのレポジトリーがこの細かい修正で汚れてしまうのを好む人はいないでしょう。そこで我々はこのツールを開発することにしました。

使用方法

ローカル環境で行ったfooというファイルの中身をaからbに変更する修正をリモート環境にあるディレクトリーに送りたい場合を考えます。

まず、ローカル環境の差分パッチをGit Ghostで作成します。

$ git ghost push
xxxxxxx yyyyyyy
$ git ghost show yyyyyyy
diff --git a/foo b/foo
index 7898192..6178079 100644
--- a/foo
+++ b/foo
@@ -1 +1 @@
-a
+b

そして、リモート環境に移動し、以下のコマンドを実行しローカル環境の修正を同期します。

$ git ghost diff HEAD
$ git ghost pull yyyyyyy
$ git ghost diff HEAD
diff --git a/foo b/foo
index 7898192..6178079 100644
--- a/foo
+++ b/foo
@@ -1 +1 @@
-a
+b

ローカル環境の修正を簡単にリモート環境に同期することができました。

このようにGit Ghostはすごくシンプルなツールですが、他のツールと連携させることで最大の効果を発揮します。例えば、Kanikoを使ってDocker imageを作成する際にローカル環境の差分を含めることもできます。ローカル環境の差分を含めたDockerイメージを作り、そのイメージを使って再現性のあるジョブを動かすArgo利用例も公開しています。

アーキテクチャ

アイデアは非常にシンプルです。このツールはリモートのレポジトリーに対してローカル環境でのコミットの差分およびコミットされていない差分のパッチを別のリポジトリで管理します。そして、リモート環境でそのパッチを適用することで、ローカル環境を再現します。細かい点ですが、ローカルコミットの差分とコミットしていない差分を別々のパッチで管理することで、ローカルコミットをリモートのレポジトリーにプッシュした際にコミットしていない差分をそのまま使うことができるようになっています。

他のツールや認証情報を不要とするため、Gitレポジトリーをパッチのストレージとして使っています。

我々はこのツールをKubernetesクラスターで使っていますが、その他の環境でも同じように使えるはずです。オンプレミスのサーバーにラップトップでの変更をトラッキングしつつ送りたいという場合でも使えます。

 

是非試しに使っていただいて、GitHubにてフィードバックをよろしくお願いします!

KubernetesのSchedulerを評価するためのシミュレーター「k8s-cluster-simulator」公開

Daisuke Taniwaki

2019-04-11 08:00:27

概要

2018年夏のインターンおよびPEとして勤務した薮内さんとそのメンターである谷脇大村で開発したKubernetesクラスターのシミュレーターであるk8s-cluster-simulatorのアルファ版をオープンソースとして公開しました。このシミュレーターはKubernetesクラスタに投入されるPodのワークロードを時間とともにシミュレートできるため、Kubernetesのスケジューラーを本番環境に投入する前に評価することができます。

開発の動機

PFNでは巨大なオンプレのGPUクラスタを持っており、その上でKubernetesを使って様々な実行時間の機械学習ジョブを研究者が実行しています。我々クラスターサービスチームのミッションの一つとして、GPUの利用率を向上させ費用対効果をあげることが挙げられます。一方で、研究者間で使えるリソースの平等さも考慮しなければなりません。これを実現させるために、我々はKubernetesのスケジューラーを独自で開発したり、Extender (例 kube-throttler)を拡張したりしています。しかし、新しく開発したロジックを本番環境で走っている機械学習ジョブに影響させずに評価するのは難しく、また頻繁に試行錯誤を本番環境上で行うのは好ましくありません。バグのあるスケジューラーをデプロイしてしまった場合には研究者の仕事を止めてしまうことになるので、絶対に避けなければなりません。またスケジューラーのアルゴリズムを試すためだけに、大規模なクラスタを用意し、多くのワークロードを実際に可動させることも現実的ではありません。これらの理由からKubernetesのスケジューラーを評価するためのクラスタのシミュレーターの開発を開始しました。

デザイン

シミュレーターを開発するにあたって以下のことを考慮しました。

  • シミュレーター用のスケジューラーの実装を最小限の変更で本番環境で動かせるようにする。
  • 時間をシミュレートすることで評価を高速化するとともに、通信や内部処理のレイテンシーがスケジューリングのロジックの評価に影響しないようにする。
  • シミュレートするワークロードを自由に設計できる。
  • 後段の分析のために様々なメトリックスを出力できる。

 

アーキテクチャ

以下は簡単なフロー図になります。

 

アイデアはすごく簡単です。シミュレーターはループのステップ毎にクロックを1つ進めます。各ステップでサブミッターにそのクロックで投入するPodがあるかどうかを聞いて、サブミッターは投入または削除するPodがあればPodのリストを返します。シミュレーターはPodのリストをスケジューラーに渡し、スケジューラーはBindするものと削除するPodを選んでイベントとして返し、シミュレーターがリソース管理を行います。そして、この時に処理されたPodのメトリックスをMetrics Loggerに出力する流れになります。

 

以下はハイレベルなクラス図になります。

 

本シミュレーターでは拡張できる点は以下の2つになります。

 

Submitters

シミュレーターの定義するインターフェースに沿っていれば任意の数、組み合わせのサブミッターを使用することができます。複数のサブミッターをシミュレーターにプラグインできるので、例えばAさんは朝たくさんのPodをサブミットする傾向があるが、Bさんは夕方たくさんのPodをサブミットする傾向があるといったシミュレーションをする場合、それぞれのユーザの振る舞いモデルを独立に開発してシミュレーターにプラグインできます。

また、サブミッターはクロック毎のメトリックスを受け取ることができるため、クラスターの利用状況に応じて挙動を変えることも可能です。

Scheduler

スケジューラーの拡張方法は2種類あります。
Kubernetesのスケジューラー(kube-scheduler)をそのままもしくは拡張したアルゴリズムを利用したい場合、kube-schedulerが用意しているのと同様, Prioritizer, Extender, Predicateをセットできるミミックスケジューラーが用意されています。kube-schedulerはキューベースのスケジューラーですが、複数のPodを条件に応じてまとめてスケジュールするような、例えばより複雑なスケジューラーをシミュレーションしたい場合には、シミュレーターが定義するインターフェースを実装するように少しラッパーメソッドを書くと、それも評価できるようになっています。

*kube-schedulerの挙動については大村によるQiita投稿をご覧ください。

ロードマップ

現在、シミュレーターの使いやすさを向上させ、またより現実的な環境をシミュレーションできるように、ベータバージョンに向けて以下の機能を開発しています。

  • より疎結合なコンポーネント(例:スケジューラーとサブミッターにRPCインターフェースをサポート)
  • よく使われるサブミッターの提供(例: 典型的な確率分布に従うサブミッター(一様分布、二項分布、ポアソン分布等)
  • より多くのクラスターイベントへの対応(ノード故障、突発的なPod故障、ノード追加、削除)
  • デファクトなプロッターツール(matplotlib, gnuplot等)で直接読み込める出力フォーマットのサポート

興味のある方は是非試していただいて、フィードバックをいただけると幸いです。