Nxバックエンド勉強会#8でお話しする内容のポジショントークです.
シリーズ
関連記事
「全世界のスマホGPUをクラスタリング」というのは,上記の関連記事にあるように @piacerex さんが言い出したことで,私のアイデアではありません.
元々はPelemay(ペレメイ)を開発したきっかけではあったのだけど,ElixirからGPUを駆動したいという要望が @piacerex さんから寄せられたのが2017年のこと.最初にそのアイデアをQiitaに書いたのが「ZEAM開発ログv0.1.1 AI/MLを爆速にしたい! Flow / GenStage でGPUを駆動できないの?」です.
この技術は,当初はファイナルファンタジーにあやかってHastega(ヘイスガ)と呼んでいました.ファイナルファンタジーにしたのは,当時日本ではElixirの名称の由来はファイナルファンタジーだと信じられていたからですね.余談ですが,Hastegaを最初に日本語で研究論文にしたときに,このElixirの名称の由来の説について言及したのです.それをElixirの原作者のJosé Valim(ジョゼ・ヴァリム)が(日本語なのに)読んでくれて,「とても面白かったよ!だけど1つだけ訂正させてくれ.私はファイナルファンタジーを一度もプレイしたことは無い」という衝撃的な話をメールしてくれたのでした.その話をErlang & Elixir Fest 2019の「超並列高速実行処理系 Hastega 〜 Lonestar ElixirConf 凱旋帰国」で披露したのは良き思い出でした.
もう1つ,余談になりますが,このときに並行して研究開発していた技術がコールバックスレッドという技術で,Qiitaには「ZEAM開発ログ v.0.2.0 Node.js と同じ原理の軽量コールバックスレッドを Elixir に実装してみた (背景編)」でアイデアを,「ZEAM開発ログ v.0.2.1 Node.js と同じ原理の軽量コールバックスレッドを Elixir に実装してみた (実装編)」で実装を紹介していました.
@piacerex さんにどちらを優先して研究開発しましょうか?と聞いたのでした.そうしたら「GPU駆動を優先したい」という要望をいただいたので,その後,この言葉の通りにGPU駆動を優先してHastega,そしてPelemayの研究開発へと勤しみます.
閑話休題.そういうわけで,ElixirからGPUを駆動するという研究開発を進めていったのですが,Hastegaの時点で,実用化には大きな技術的課題がいくつかあることがわかりました.まず,Elixir側のデータ構造がリストだったために,配列との相互変換にO(n),つまりリストのサイズに比例した変換時間を要したことと,CPUとGPUの間でデータをやり取りするためには,通常のPCの場合,PCIeバスの転送時間を要したことでした.この技術的課題のため,Hastegaでの評価では,GPUで実行するよりもCPUでマルチコア駆動した方が高速になるという結果が得られたのでした.
この技術的課題を克服するために当時下した判断は,「GPU駆動を確立するより前に,まずマルチコアCPUを使いこなす技術を研究開発しよう」「それによって,リストから配列に変換することと,CPUからGPUに転送することを,並列に実行するような処理系を作ることを目指そう」ということでした.
もう1つ別の技術的課題がありました.HastegaではElixirからRustを呼び出すという構成にしており,プロトタイプであったため,Rustのコードはあらかじめ作り込んだ演算を手で実装していました.実用化に向けては,Elixirのコードをもとにしてネイティブコードを生成するJust in timeコンパイラ(JIT)を実現する必要があったのですが,コンパイルエラーが起きないようにRustのコードを自動生成することが極めて困難であるという技術的課題に直面したのでした.
この技術的課題を解決するために,次の段階でフルスクラッチで開発したPelemayでは,Rustをやめて,コード生成が容易なCを採用することにしました.そうしたところ,Rustの時にはrayonというライブラリを採用することで簡単にマルチコアCPU上で並列化できたのですが(「ZEAM開発ログ v.0.3.2 rayon によるSIMD(SSE2)マルチコアCPUによりOpenCL + GPUを上回るパフォーマンスが出た件」),Cの時にNIFで用意されているマルチスレッド(erl_nifにあるAPI)を使おうとして四苦八苦することになりました.試作に試作を重ねていたのですが,複雑になりすぎて安定して動作させることができなかったので,この方向性を断念し,ElixirでマルチコアCPU上で並列化し,それぞれのプロセスでネイティブコード実行してSIMD並列化するというアプローチを採用することにしました.
それによって生まれたのが,PelemayFp(ペレメイ・エフ・ピー)です.これはFlowよりも高速に並列化できるように,かつFlowと異なってデータを整列させたまま実行できるよう,注意深くフルスクラッチで開発したOSSです.「Elixirで速度を追い求めるときのプログラミングスタイル」にあるような地道な実験を繰り返して実装しました.
そうしたところ,Joséが2020年にNx(エヌエックス)を発表します.これはPelemayとは異なるアプローチで,Elixirを機械学習に用い,GPUを駆動する仕組みを提案したものです.Pelemayで技術的課題としていたリストからのデータ変換時間を要する問題については,Nxではバイナリというデータ構造を基軸とすることでデータ変換の必要性をそもそも無くすという解決アプローチを採用しました.
Nxは,バックエンドを差し替えられるという特徴を持っています.バックエンドを自由に定義できるという技術的なフロンティアを提供したのです.これにより,より高速なNx処理系を追い求める競争が始まりました.
この競争の先頭を走るのはEXLA(イー・エックス・エル・エー: 作者のSean Moriarityがそう発音していました.イグジラではなかったです)とTorchX(トーチ・エックス)です.そしてアジア勢が開発を進める,Evision(イー・ビジョン),Manx(マンクス),そして私のPelemay Backend(ペレメイ・バックエンド)です.
Pelemay Backendは,FAISの旭興産グループ研究支援プログラムの支援を受けて研究開発を進めてきました.BLAS(ブラス: Basic Linear Algebra Subprograms)という線形代数学演算の定番ライブラリを基調とした中間表現を定義し,NxバックエンドのAPIからこの中間表現を生成・実行するJITを備える方式で設計しています.この中間表現とJITは,マルチコアCPUとGPUを組み合わせたコンピュータ・ユニットで構成されるコンピュータ・クラスタ上で分散・並列処理できるように設計されています.これについては,第64回プログラミング・シンポジウムで発表する予定です.
折しも,Elixir Desktopの登場により,iOSやAndroid上でLiveviewベースのネイティブアプリを動かすことができるようになりました.それを受けて,Pelemay BackendをiOSやAndroid上で動作させることについても研究開発を進めています.iOSでの動作ではEvisionの作者のCocoaさんが先行しているので,Cocoaさんに教えを乞いながら進めています.