Crystal言語がはやい

投稿者: | 2018年2月3日

すごい!

素人でも気軽にたのしくRubyで高速計算する方法を探してきた。そしてNArrayをみつけた。しかし、数年ぶりにNArrayを超えるかもしれない逸材を発見してしまった。Crystal言語である。Crystal言語は、マルチプロセスに対応する気もあるらしく、xargsやparalellジェムを日々愛用している私はとても期待している。そんなCrystalのメモ。

開発者

アルゼンチンに住んでいる

コンパイル

速度比較

色々な言語で計算速度を比較してみたを参考にライプニッツ級数の計算で測定した。グラフを見ると、Rubyと全く同じコードにも関わらず、コンパイル時間を含めてもNArrayより早いことがわかる。これはただ事ではない。PCによってはもっと差が出る印象。

Ruby & Crystal

NArray

 realusersys
Ruby61.887s61.812s0.028s
Crystal (コンパイル&実行)7.923s7.900s0.196s
Crystal (最適化コンパイルしたものを実行)6.821s6.812s0.000s
Numo::NArray10.163s9.860s0.256s

ほんの少しさわってイマイチに感じるところ

半日さわった印象としては、型のキャストがわかりにくい。たとえばUInt8をfloat32やfloat32に変換する方法をググってもしばらく見つけられなかった。.to_fでよいらしいが、.as(Float64)とかで統一してくれた方わかりやすい気もする。あと、どうしてもコンパイルに時間がかかる。kemal(sinatra相当)使ったコードをコンパイルするだけで体感数秒以上かかる。GUIライブラリが弱くてキャンバスに図形描写したりするの苦手っぽい。ライブラリ眺めてる pointerof とか出てくる。コンピュータに強い人にとっては長所なんだろうけど。

よいところ

crystal shards コマンドが優秀。Rubyもこうあるべきだと思う。htop眺めてると、files = Dir.glob files.each とかやったときに自動的にマルチスレッドしてくれているっぽい。だいたいRubyと同じ。コミュニティの雰囲気も洗練されていて悪くなさそう。とにかく処理が早い。

追記:さらに1日さわってRubyとの違いを感じたところ

上記は、数値計算のことだけを考えていたので、オブジェクト指向の部分、クラスやメソッドなども少し触ってみたらRubyとかなり違いがあった。まずは型チェックが厳しい。ある程度はコンパイラ?が型を推測してくれるが、必ずしも推測万能ではないので、推測が難しいところは自分で型を指定していく必要がある。特に引数のチェックは厳しい。Arrayとかは最初に型を指定する。こんな制約もあるので何でもかんでもArrayを使うべきではなく、構造体とかタプルとかSliceとか用途に合った型の採用を検討するほうがいいかも。デバックの時にRubyとはかなり頭の切り替えが必要そう。いろんな型を受け取るメソッドはオーバーライドという書き方も使って行く。ゲッター、セッターは、attr_readerの代わりにgetterとか名前が違う。irbがないので、crystal playを使う。(こういうのはRubyにも搭載されているべき。Jupyterに依存するべきではないと思う。)cloneとかequalとかto_jsonとか動かないので、自分でコードを書く必要がある。そして便利なマクロが用意されているので、それを使う。マクロは便利そうだが直感的になんとなく闇を感じる。2つobjectをreternするときはタプルが便利。injectのかわりにreduce、””と”意味が違う、require_relativeない。プライベートメソッドはprivate def hogeと書く。Threadとかも何気に動くっぽいけど、spawn使えとのこと。forkもあるっぽいが試していない。RubyはC言語のライブラリをラッパーになって処理を呼んでるだけの場合も多く、そういうものはCrystalに書き直しても大して早くならない。そのため「Crystalizationで爆速!」が(俺の趣味レベルで)実現できる範囲は思ったより狭いかも。コミュニティ若いので、ちょっとドキュメント書くだけでも歓迎される雰囲気がある。すごい。

使い分け

NArrayの方が可読性がよいので、特にスピードを求める部分だけCrystalで書けばいいと思う。素人なので、難しいことは考えずにパイプでつないだり、普通に実行結果をファイルに保存して、処理をつないでいけばよいと思う。Rubexとかもいいけど、やっぱり簡単な方がいい。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です