TA小話
〜Ruby拡張ライブラリを作る〜
東大 数理 M1 45-136035
谷村 慈則
モチベーション
●
Ruby(スクリプト言語)の特徴
長所:小回りが効く。 短所:計算が遅い。
●
C言語の特徴
長所:計算が速い。 短所:色々と重い。
→C言語にメインの計算をさせて、
Rubyで細かい調整をしよう!!!
2つの解決策
●
標準出力によるやりとり
パイプなどを用いてデータをプログラム間で受け渡しをする。 愚直でシンプルだし汎用性もあるが、標準出力を読み込む部 分をいちいち記述するのは結構面倒。
●
拡張ライブラリを自作
C言語を用いてRubyの関数を記述する。
Rubyのシンプルな文法に自然な形でC言語による計算 部分を組み込むことができる!!
実際にやってみた
●
どれくらいの速さなのかを比較実験した。
●
同一のアルゴリズムを複数の言語で実行し
て時間を計測する。
●
それぞれの言語に対する最適化などについ
ては敢えて考えず、出来る限り「コピペ」で済
ませた。
プログラム・実行・計測
●
Newton法で1から99999までの平方根を求める
プログラムを作成した。
●
プログラムはrootを計算する関数の部分と1から
99999までの数字をその関数に代入するメインの
部分に分けた。
●
特に、拡張ライブラリについては、関数部分をC言語
で記述し、メインの部分をRubyで記述した。
●
コンパイラなどはもともとパソコンにダウンロードし
てあったものを用いた。小細工はない(はず)。
結果
Ruby+C Ruby C D Java
0.12s 5.15s 0.05s 0.10s 0.16s
D言語やJavaと同様
の計算能力を発揮!!!
注意
●
今回はRubyを用いたが、勿論、Pythonなどの他
のスクリプト言語でも同様のことができる。(はず)
●
今回は条件を揃えるためにコピペで実験を行った
が、当然のことながらD言語やJavaにも得意とする
状況は存在するため、この実験から一概にどの言
語・方法が”優れている”ということは言えない。
roottest.c その1
#include <ruby.h>
double preroot(double n){ double x,d;
int i;
x = n / 2; d = 100;
while(d > n * 1.0e-15){
x = x - (x*x - n) / (2*x); d = x * x - n;
if(d < 0) d = - d; }
return x; }
roottest.c その2
VALUE root(VALUE self,VALUE y){ double n = NUM2DBL(y);
n = preroot(n);
return rb_float_new(n); }
void Init_Root(void){ VALUE rb_mRoot;
rb_mRoot = rb_define_module("Root");
rb_define_module_function(rb_mRoot,"root",root,1);