バッテリー駆動GPUで実現する野外データ分析活動、略して野デブ

電源とネットワーク接続に制約がある野外で、データ分析処理をいかにして完遂するか。市販のノートパソコンと搭載GPUを活用して処理時間と消費電力の問題を解決したはなし。

# 筆者の問題

筆者は[アスリート向けデータ分析](http://funride.jp/report/whpsc_2017/)の一環で $40^{64}$ の組み合わせから最適な組み合わせを選びだす類の処理を頻繁に実行しています。さまざまなパラメーターで物理シミュレーションを実行し、遺伝的アルゴリズムにより"進化"した優れたパラメーターの組み合わせを導きだします。その手続きは

1. パラメーター(遺伝子)の異なる3000件の個体を生成
2. 3000件の個体をそれぞれ物理シミュレーション
2. シミュレーション結果から成績の良い"遺伝子"を選出
3. 優良な遺伝子を元に交配・突然変異して新しい世代の個体3000件を生成

のくりかえし。このうち1世代あたり3000件の物理シミュレーション部分がどうにも計算量がおおくて悩ましい。

[![TT Optimizerデモ動画](https://img.youtube.com/vi/SXIda8ip0qQ/0.jpg)](https://www.youtube.com/watch?v=SXIda8ip0qQ)

1000〜1500回ほどの世代交代を経て準最適解(優良な遺伝子)を探索するのですが、C言語で実装したこれらの処理を[MacBook Pro (15-inch, 2017)](https://support.apple.com/kb/SP756?viewlocale=ja_JP&locale=ja_JP)で実行すると10分ほどかかります。さらに前提条件の異なる48パターンで実施するので、総実行時間は8時間を要します。ワケあって筆者はこの処理を離島や山間部などの野外でやりたいのですが、これではとてもバッテリーが持ちません。
とりあえず「時代はクラウドだよね」ということでAWS EC2 m3.mediumインスタンス10台に分散処理することで1時間、必要ならばインスタンスを追加してさらに短時間で処理できるようにはしましたが、この構成ではタスク投入と結果の回収にネットワーク接続が必要でやはり野外での利用に難があります。


# GPUへのオフロード

そこでMacBook Proに搭載されているdGPU [AMD Radeon Pro 560](https://www.amd.com/ja/graphics/workstations-radeon-pro-500)を使うことにします。このGPUは16台の演算ユニットにストリームプロセッサが合計1024基とGPGPUとしてなかなかのスペック。AMDのGPUなのであたりまえにCUDAは使えませんし、macOSはOpenCLサポートに消極的というか非推奨。なので今回は[Metal](https://developer.apple.com/jp/metal/)を使います。C言語で実装していた物理シミュレーションと遺伝的アルゴリズムの交配・突然変異処理を[Metal Shading Language](https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf)(だいたいC++14)に移植して、遺伝的アルゴリズムのランキング処理と可視化はSwiftで実装します。
ちなみに、物理シミュレーション部分はループと条件分岐が多数含まれているため、GPUにはあまり適していない実装ですが気にしないことにします。


# Performance per Wattによる性能評価

CPU C言語実装シングルスレッドでは2.4世代/secで処理していたところ、dGPU Metal/Swift実装は41世代/sec処理できるようになりました。処理速度だけを評価すると約17倍。これだけでも十分な向上ですが、バッテリー駆動させたいので消費電力が爆発していては困ります。
そこでバッテリー駆動時の消費電力をチェックします。バッテリー駆動時の供給電流と電圧は `$ system_profiler  SPPowerDataType | grep 'Amperage\|Voltage'` で参照できます。CPU C言語実装シングルスレッド、dGPU Metal/Swift実装それぞれの実行時の電流を計測した結果をまとめます。

| 構成 | 1秒あたりのタスク処理数 | 供給電流 | 消費電力| 1ワットあたりのタスク数 | 内蔵バッテリーが処理できるタスク数|
|-----|----|-----|--------------|-------------------|------------------------------|
| CPU C言語 x1スレッド | 2.4 世代/sec | 2,423 mA | 28.2 W |  0.085 世代/W | 約23,000 世代　|
| dGPU Metal/Swift| 41 世代/sec  | 3,016 mA | 35.1 W | 1.17 世代/W | 約320,000 世代 |
_* Wi-Fiオフ、Bluetoothオフ、バックライト50%、空調下で計測_
_** 内蔵バッテリー容量 76 Wh_

1ワットで処理できるタスク数が約14倍に向上しました。バッテリー駆動でも約32万世代の試行ができる余裕のデータ分析環境です。
ちなみにCPU C言語実装を x8スレッドで実行すると 0.23 世代/Wとなり、ギリギリ要件を満たせそうにも見えますが、再試行する余裕がまったくないギリギリぐあいなので選択肢になりませんでした。あと消費電力 55W はスッゲェ熱い。やはりGPUは省エネ。

# まとめ

MacBook Proに搭載されているdGPUを活用することで、処理時間と消費電力の問題を一度に解決できました。ただし単位時間あたりの消費電力は増加しているので、暑熱環境で連続稼働する場合はパフォーマンスを維持できない可能性があります。こちらは別の話題として機会があれば調べてみます。
何はともあれ。処理時間と消費電力の問題は解決できたので、ネットワークなしのバッテリー駆動でも野外データ分析活動、略して 野デブ△ が捗りますね。

# 参考

* [コンピュータープログラマが自転車世界最速チャレンジをサポートしてきた話, FUNRiDE](http://funride.jp/report/whpsc_2017/)
* [MacBook Pro (15-inch, 2017)技術仕様, Apple Inc.](https://support.apple.com/kb/SP756?viewlocale=ja_JP&locale=ja_JP)
* [Radeon™ Pro 500シリーズ・グラフィックス・カード, Advanced Micro Devices, Inc](https://www.amd.com/ja/graphics/workstations-radeon-pro-500)
* [Metal 2, Apple Inc.](https://developer.apple.com/jp/metal/)
* [Metal Shading Language Specification version 2.1, Apple Inc.](https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf)
* [Performance per watt, Wikipedia](https://en.wikipedia.org/wiki/Performance_per_watt)