Ruby の Bignum は自力で多倍長整数演算を行っていますが、あまり速くないです。そこで、GMP を使うようにするパッチを書いてみました。GMP (The GNU MP Bignum Library) は gcc なんかも使ってるらしい多倍長整数ライブラリ *1 で、そこそこチューニングされているようです。
http://dame.dyndns.org/misc/misc/ruby-1.9.1-p0-gmp-bignum.patch
以前多倍長演算の速度比較をしたときに使った題材で、パッチ前とパッチ後の速度を比較してみました。
- 5 の 1000000 乗を計算する時間: 5.887 秒 → 0.075 秒
- 5 の 1000000 乗を計算して 10 進数表示する時間: 36.485 秒 → 0.939 秒
- 円周率を 10000 桁計算する時間: 3.885 秒 → 1.022 秒
いやー速いですね。
パッチの使い方は以下の通り。
$ wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p0.tar.bz2 $ wget http://dame.dyndns.org/misc/misc/ruby-1.9.1-p0-gmp-bignum.patch $ tar xjf ruby-1.9.1-p0.tar.bz2 $ cd ruby-1.9.1-p0 $ patch -p1 < ../ruby-1.9.1-p0-gmp-bignum.patch $ ./configure --enable-gmp $ make
さて、このパッチを本体に統合するよう提案しようかと思ったのですが、結構問題がありそうです。
- 互換性: struct RBignum の構造が変わる。RBIGNUM_LEN や RBIGNUM_DIGITS もなくなる。この辺って公開 API ?
- メンテナンス: bignum.c が #ifdef だらけになって、かなり見通しが悪くなる。リファクタリングは面倒くさそう。
- テスト: make test と make test-all はそれなりに通ったけど、あんまりちゃんとテストしてない。i686-linux 以外の環境とか。
- ライセンス: GMP (LGPL) を呼ぶコードがコアに入っても大丈夫かな?
- 利便性: ビルド時にオプションを指定しないと使えない *2 。コンパイル済みのパッケージを使う一般ユーザには無縁になるかも。
- 需要: そもそも、Ruby の多倍長整数演算が速くなって喜ぶ人はどのくらいいるのか?
うーん。どうしたらなるべく面倒なく便利にできるかなあ。
ついでに、だいたい trunk 用のパッチ。
http://dame.dyndns.org/misc/misc/ruby-1.9-r23296-gmp-bignum.patch