GMP で Bignum を高速化するパッチ

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

*1:正確には多倍長浮動小数点数有理数もあるみたい? mpfr との関係は知らない。

*2:require "gmp-bignum" としたら gmp 版になる、とかできたらいいんだけど、require 前に作られた Bignum と共存することになって面倒そう。