id:tokuhiromにそそのかされれてCrypt::DH::GMP (リンクはそのうち出現します)書きました。Crypt::DHってモジュールがあって、これに依存するモジュールが少々あるわけですが、このモジュールがすこぶる遅いわけですな。なんで遅いかというとこのモジュールは裏でMath::BigIntを使っているから。Math::BigInt自体はいわゆる任意精度数演算ライブラリで、これをポータブルな方法でPerl上で動作させるにはとてもよくできたモジュールです。
が。遅い。
裏でlibgmpやPari等を使っても、それでも遅い。その理由は単純で、Math::BigIntを使うと裏で何回も何回もSV -> mpz_t -> SV等の変換を含めた、「Perlらしい手法が実現できるための処理」が行われるからです。
Crypt::DHのソースコードを読む限り、Crypt::DHが行っている計算はたいしたことではない。だったら、普通にC structの中にmpz_t構造体を何個かもって、それらを使って直接GMPで計算したら速いんでないの?というのが今回のモジュールの趣旨です。まぁ、このモジュールだとlibgmpが必須になるから敷居が高くなるんだけど、どうせ実用的なレベルで計算を行うにはlibgmp必須だし、いいじゃん?ということで作ってみた。ちなみにソースコードのほとんどは半蔵門線車内の渋谷→大手町間で書いたよ!
さて、とりあえずうごくようになったのベンチマークを・・・と思ってベンチマークを動かしてみたら、これが遅い遅い。なんじゃこのスピード。全く話にならないので、ベンチを5000回から100回まで落としてみたらとりあえず走った。
daisuke@beefcake Crypt-DH-GMP$ perl -Mblib tools/benchmark.pl
Rate pp gmp
pp 1.70/s -- -98%
gmp 112/s 6526% --
まぁ、速いことは実証できたかな。長いベンチマークは寝てる間にでも走らせておく。
あと、Crypt::DHはMath::BigIntオブジェクトを返すようになっているので、そのあたりの互換性を保つために-compatオプションを指定できるようにしておいた。以下のようにしておくと、今までのCrypt::DHを使っているモジュールでもCrypt::DH::GMPを使える・・・はず。
use Crypt::DH;
use Crypt::DH::GMP qw(-compat);
まだちゃんと使ってないので人柱歓迎です。
コメント