Perl Advent Calendar 2017 2日目「SPVMという言語について語る」
この記事は、Perl Advent Calender 2日目の記事です。1日目はK君でしたね。
先週は妻の実家に帰っていて、甥っ子ちゃんと遊びました。そのあと、カラオケいって、バッティングセンター行ったら、ちょっと疲れて風邪をひいちゃいました。
さて、本題へ。
SPVMの開発の動機
もともとは、Perlの集合演算を速くしたいなぁとずっと思っていて、RstatsというR言語のライブラリを、Perlに移植するプロジェクトをやっていました。これはC++とXSで書いていたのですけれど、関数を実装するためには、C++とXSで書かなくっちゃいけなくってちょっと辛い。
集合演算というのは、まぁ、簡単にいうと、配列の足し算や引き算や掛け算や割り算のことです。たとえば、10万の長さの二つの配列の要素を足し算して、結果として返すというようなことですね。
Perlの配列の足し算は、かなり遅い。C++とXSで書くと、速くできる。だから、集合演算ライブラリを書いて、Perlから呼び出すというのが、Rstatsの基本的な考えでした。
けれども、これは、柔軟性という点で、さまざまな問題を抱えていることがわかりました。
新しい集合演算の関数を作りにくい
新しく集合演算を定義したいと思ったとき、たとえば三角関数を配列に作用させて結果を受け取りたい、といった場合に、その関数を、XSとC++で書かないといけない。でも、XSはXSレベルでは、モジュール性がないので、他のモジュールから参照できないんです。
モジュールユーザーが、新しく集合演算の関数を作りたい場合に、簡単に対応することができない。これが、一つ目の問題です。
集合演算は、条件分岐に弱い
もうひとつの問題は、集合演算は条件分岐に弱いということです。単純な演算だといいのですが、基本的には、プログラミングというのは、条件分岐のかたまりのようなものです。この条件のときには、こうしたい。この条件のときは、こうしたい。そういうことばかりが書かれるのが、プログラミングです。
集合演算ライブラリは、単純な、条件分岐ができない。集合演算ライブラリを使って、条件分岐を書きたい場合は、論理和、論理積、否定も、集合演算を使う必要があるんだけれど、これが、かなりめんどくさい。10万個の配列が二つあれば、さらに、10万個の配列を準備して、論理和の結果を取り出すみたいなことをしないといけない。メモリリソースもかなり使う。
だから、Perlで集合演算を行うインフラフラストラクチャとして、どうしても、集合演算ライブラリではなくって、配列の演算を高速で行える、静的なプログラミング言語が必要だなぁという結論になった。
静的なプログラミング言語を使って、集合演算ライブラリを構築することで、非常に簡潔に、柔軟に、集合演算を行うことができるはず。
メモリリソースを扱いにくい
集合演算のもう一つの問題点は、メモリリソース確保の問題だ。
たとえば、ライブラリの関数で、新しくメモリを確保して返すというものになっている場合、配列の要素10万個のメモリ対して、新しく配列の要素10万個のメモリを確保するということになる。
ライブラリではなくって、静的なプログラミング言語であれば、元の要素に対して、演算するということが簡単にできる。メモリリソースの調節を簡単にできるということだ。
AI(人工知能)が話題になり続けている
今、インターネットやテレビでは、人工知能が話題になり続けている。僕も、本屋で脳・心・人工知能 数理で脳を解き明かすという本を一冊、読んでみた。
プログラミングの観点からいえば、人工知能プログラミングに、何が必須かといえば、GPUを使った、高速な並列処理プログラミングだなと思った。たとえば、次のような数値計算を莫大な量行わないといけない。
output = weight1 * intput1 + weight2 * intput2 + ... + weightn * weightn
もしこれに対して、Perlが適用しようと思うならば「連続した領域のデータ構造」と「GPUのライブラリを簡単にバインディング」できることが必要だ。AI::MXNetという人工知能ライブラリがPerlにある。
AI::MXNetはC++のライブラリをPerlのXSを使って、バインディグしている。これは、一つの解決策なのだけれど、大きな問題としては、ユーザーがライブラリを追加したいという場合と、集合演算は条件分岐が苦手なので、その部分でPerlは遅いように思う。
SPVMという静的言語のプログラミングの層が一つ間に入れば、パフォーマンス面とメモリリソース確保の問題を解決できるように思う。
SPVMの仕組み
SPVMはPerlではないんです。SPVMはPerl風静的プログラミング言語です。静的型を持つということを除いて、Perlに限りなく近い文法で、書くことができるCPANモジュールです。
# lib/SPVM/MyMath.spvm package MyMath { # Sub Declaration sub sum ($nums : int[]) : int { # Culcurate total my $total = 0; for (my $i = 0; $i < @$nums; $i++) { $total += $nums->[$i]; } return $total; } }
SPVMの目標
SPVMは次の主要な目標を持っています。
- 集合演算に適したデータ構造をPerlに追加すること。つまり、連続した領域を持つ配列をPerlから扱えるようにすること。
- 配列のループ処理をPerlの30倍の速度にする。理想はC言語で最適化されたパフォーマンスを出せること。
- C言語で書かれた、GPUやSIMDの並列処理を簡単にバインディングできること
具体的な内容でいうと、SPVMの機能を利用することで、Perl言語を人工知能とビッグデータに対応できるようにすることです。
SPVMの現状
言語仕様は、90%くらいはできていて、実装もできてきて、Perlから実行できるようになっています。インストールも簡単にすぐに終わります。
cpanm SPVM
目標1の集合演算に適したデータ構造を追加するというのは、達成しています。目標3のバインディングについては、仕様が少し変わる可能性がありますが、動かすことができます。
目標2のパフォーマンスは、まだ目標に到達していません。現状は、Javaバイトコードに似た、バイトコードを実行する仕組みになっていて、これをJITの実装に変えることで、目標に近づけようと奮闘しているところです。
JITの実装に加えて、ループ最適化を施すことで、さらに目標に近づけることができそうです。
明日は参加者がまだいないみたいなので、書いてみたい方は、参加をどうぞ!