Ruby 処理系での軽量な浮動小数点数表現
笹

田

耕

一†

オブジェクト指向スクリプト言語 Ruby は変数に型の無い動的なプログラミング言語であり，コン
ポーネントを組み合わせる糊付け言語のとしての特徴を有する．Ruby 処理系ではこの動的な型を実現するために，オブジェクトごとに型情報を含めた領域を割り当て，オブジェクトをその領域へのポインタ値で表現する．この方式では各オブジェクトごとに領域を割り当てることになりメモリ効率が悪い．とくに，現在の Ruby 処理系では浮動小数点数 1 つに 1 つの領域を割り当てるため効率が悪い．そこで，本稿では 64 ビット CPU を用いて浮動小数点数をポインタ型に埋め込む方式を提案する．本稿では現状の Ruby 処理系でのデータ構造，とくに浮動小数点数のデータ表現について説明する．そして，提案する浮動小数点数の表現方式について述べ，実装し評価した結果を述べる．

A Lightweight Representation of Floting-Point Numbers
on Ruby Interpreter
Koichi Sasada†

Ruby is an object-oriented, dynamic, programming language. For example, all variables are
not typed. This feature is useful for combining components as a glue language. The Ruby
interpreter represents every object as a pointer to an entity in heap memory. An object entity
includes the object type and other information. However, this representation can be inefficient because every object needs an entity in heap memory. Especially, the representation of
floating-point (FP) is inefficient because numbers as a double precision value needs additional
object header. To solve this issue, we propose an efficient representation of Ruby’s FP numbers on 64bit CPUs. The idea is simple: represent the FP object as an encoded, immediate
pointer value similar to Ruby’s Fixnum representation. In this paper, we describe an object
representation for the Ruby interpreter, showing the proposed method and the evaluation
results.

1. は じ め にている．このオブジェクトの表現手法は動的な型をもつプログラミング言語を実装する一般的な手法である．

オブジェクト指向スクリプト言語 Ruby15)14)（以降

Ruby では浮動小数点数の計算もサポートしている．

Ruby）は，その使いやすさから世界中で利用されてRuby で計算時間のかかる数値計算を行うことは，現在いるプログラミング言語である16) ．Ruby の特徴の 1の処理系の速度的な制約からあまり行われることは無

つに動的な言語仕様がある．たとえば，変数に対して

いが，C 言語などで記述された既存の数値計算ライブ

格納するオブジェクトのクラスを記述する必要がなく，

ラリへのインターフェースとして利用したり，大規模

どのようなクラスのオブジェクトも任意の変数に格納な数値計算のプロトタイプとして記述力の高い Ruby

することができる．この機能により，Ruby を様々なを利用するなど，Ruby での浮動小数点数を利用したコンポーネントを組み合わせて目的のソフトウェアを

数値計算の需要がある．とくに，Ruby の記述力の高構築するために必要な糊付け言語として利用することさから，より高速に実行できるのであれば Ruby で数ができる．

値計算を行いたい，という声を聞く．

Ruby では，基本的に各オブジェクトのアイデンティ

Ruby での浮動小数点数は，C 言語の double 型で表ティをヒープ上に配置した領域へのポインタとして表現される倍精度浮動小数点数であり，Float オブジェ現している．ポインタが指し示す領域に，それぞれオクトとして利用できる．現在の Ruby 処理系では，他

ブジェクトごとにそのオブジェクトがどのような情報のオブジェクトと同様に Float オブジェクトそれぞを保持しているのかを示す情報や，そのオブジェクト

れにヒープ上の領域を確保することで実現している．

のクラスを示す情報などを記録するヘッダ部を格納しこれは，Float オブジェクトごとにヘッダ部を保持す† 東京大学大学院情報理工学系研究科
Graduate School of Information Science and Technology, The University of Tokyo

るためメモリ効率が悪い．とくに，近年広く利用されている 64 ビット CPU 上では，実際に表現したい

double 型の値に比べ，ヘッダ部が大きく効率が悪い．

また，浮動小数点数を利用した計算結果ごとに Float

struct RBasic {オブジェクトを生成するため，ガーベージコレクショ

VALUE flags;

ンを頻繁に起動することになり実行時間に大きな影響

VALUE klass;

を与えており，Ruby で数値計算が大きな要因の 1 つ};となっている．

図 1 ヘッダを表現する RBasic 構造体

そこで，本稿では 64 ビット CPU 上において，Float
オブジェクトの表現をヒープ上の実体の割り当てをほstruct RString {ぼ不要とする方式について提案する．基本的なアイ

struct RBasic basic;

デアは Ruby の固定範囲の整数値である Fixnum オブ

long len;

ジェクトを表現する手法と同様に，ポインタを格納す

char *ptr;

る領域にポインタではない，という印（タグ）を付け

VALUE aux;

ることで実現する（unbox 化する）．unbox 化にはタ};グを付加するための領域が必要となるが，現在の計算機環境での double 型の浮動小数点数が IEEE 754

図 2 文字列表現

1)5)

規格で規定されている倍精度浮動小数点数でメモリ上クトの情報が格納されているヒープ上の領域へのポイに格納されることを利用して，64 ビットの精度を落ンタとなっている．その領域は RVALUE☆ データ構造とさずにタグを付加し，効率的な Float オブジェクトとして規定されている．

の表現手法を実現する．

RVALUE データ構造は，2 ワードのヘッダ部と 3

本稿で提案する手法により，Ruby における浮動小

ワードの本体部の合計 5 ワードのデータである．ヘッ

数点数を利用した数値計算において，メモリ確保やダ部を表現するのは図 1 で示す RBasic 構造体である．

ガーベージコレクションのオーバヘッドを排除し，以RBasic 構造体の flags メンバにこのデータ表現の型

前よりも高速な数値計算を可能とした．

（データ型）や GC に必要となるデータ領域（1 bit），

なお，本稿で対象とする Ruby 処理系とは，C 言語

型ごとに必要となる情報が格納されており，klass メ

で記述している仮想マシン YARV17) を導入した Ruby

ンバにはこのオブジェクトが属するクラスオブジェク

1.9.0 を示す．

トへの参照を保持している☆☆ ．

本稿では，2 章で Ruby でのオブジェクトの一般的

Ruby のメモリ管理はこの RVALUE の獲得，解放にな表現手法を説明し，Float オブジェクトの表現手法

よって行われる．Ruby 処理系はヒープ上に RVALUEを述べ，現在の Ruby 処理系での表現手法の問題点をの集合を用意しておき，オブジェクト生成時にはこの述べる．3 章で，64 ビット CPU 上での効率的な浮動集合から RVALUE 要素を 1 つ切り出す．取り出す

小数点数表現の手法について提案する．4 章で提案手ことができる RVALUE が無くなったとき，もしくは法を実装し，評価を行った結果を示し，5 章で関連研

malloc() によって獲得したメモリ使用量が閾値を超え究を述べ，6 章でまとめる．

たときにガーベージコレクション（GC）を行い，参2. Ruby オブジェクトの表現
本章では現在の Ruby 処理系でのオブジェクトの表

照のない RVALUE を回収する．回収しても必要な

RVALUE が確保できなかった場合，RVALUE の集合を新たに malloc() によって加える．

現手法と浮動小数点数の表現手法を述べる．そして，本体部の利用方法やデータ構造のレイアウトはデー

現在の浮動小数点数の表現が非効率であり，数値計算

タ型ごとに異なっている．例として文字列データ型とにおけるボトルネックの一因であることを示す．

配列データ型を示す．

なお，本章で述べる内容は文献 18) に詳しいので詳細はそちらを参照されたい．

文字列データ型（図 2）では，本体部の len メンバに文字列の長さ，ptr メンバに文字列の実体が格納さ

2.1 ポインタ参照による表現

れている．aux メンバは文字列の共有などに使う．配C プログラム中で Ruby のオブジェクトを格納する

列データ型（図 3）では len メンバに配列の長さ，ptr型として VALUE 型が用意されている．VALUE 型はそのに VALUE 型を格納するための配列の実体，aux に配実行環境でのポインタ型と同じサイズの型となってお列のキャパシティなどを記録してある．文字列，配列

り，一般的に 32 ビット CPU では 4 バイト，64 ビッ

ともに，計算の対象とする領域は ptr メンバが指し示

ト CPU では 8 バイトの大きさを持つ．なお，本稿ではポインタ型のサイズを 1 ワードと数える．
後述する VALUE 埋め込み表現を用いない，ほとん
どの Ruby オブジェクトでは VALUE 型がそのオブジェ☆

RVALUE データ構造は Ruby のソースコード gc.c 中で共用体として宣言されている．
☆☆
メンバ名が class でない理由は，テキストエディタなどで C++のキーワード class を特別扱いするからである

struct RArray {struct RFloat {struct RBasic basic;

struct RBasic basic;

long len;double float_value;

VALUE *ptr;};
図 4 Float オブジェクトの RVALUE 表現

VALUE aux;};
図 3 配列表現

きる範囲の整数を Fixnum オブジェクトとして表現可能である．64 ビット CPU では同様に 63 ビットで表すメモリ領域にある．このメモリ領域は malloc() に現できる整数を表現する☆ ．なお，Ruby では計算中よって獲得され，GC によってそのオブジェクトが回に Fixnum の範囲を超えた整数は自動的に Bignum オ

収・解放されるときに free() によって解放される．

ブジェクトに拡張されるようになっている．Bignum

なお，Ruby 1.9 からは長さが短い文字列や配列はは RVALUE によって表現されており，ヒープ上に確

RVALUE の領域中にデータの実体を記録するように保されるため，メモリが許す限り大きな数が表現可能

してメモリ使用量の最適化が施されている．これによである．

り，小さな領域のために malloc() と free() を繰り返すことがなくなった．

VALUE 型の値の下位 8 ビットが 16 進数で 1e のとき
は Symbol オブジェクトとして扱われる．Symbol オ

文字列と配列以外のデータ型については，ユーザ定

ブジェクトを示す VALUE 型のデータには，タグに利用

義オブジェクト，クラス，モジュール，正規表現，ハッする下位 8 ビット以外の領域，つまり 32 ビット CPU

シュ，Ruby レベル構造体，Bignum，ファイル，拡張

で 24 ビット，64 ビット CPU で 56 ビットの領域に用データ，そして浮動小数点数を示す Float データ型

シンボル表のキーが格納されている．

がある．このデータ型の表現方法については後述する．

2.2 VALUE 埋め込み表現

なお，本論文では C 言語の表現に則り 0x1e のように 16 進数を表記する．

Ruby プログラミングで利用するデータはすべてオブ

true, false, nil オブジェクトはそれぞれ 1 つのジェクトなので，例えば 1 のような整数もオブジェクト

値しか存在しないので，VALUE 型の値がそれぞれ 0x02，として扱われる．しかし，このような整数を RVALUE

0x00，0x04 のときにそれらのオブジェクトとして認

データ構造として割り当て，解放を管理すると非効率識される☆☆ ．

なので，VALUE 型はヒープ上のオブジェクト実体へのVALUE 埋め込み表現では RVALUE の割り当て・

ポインタ以外も格納可能なような設計になっている．

解放が不要なので，実行時間的にもメモリ消費量的に

RVALUE データへのポインタは 4 バイトアライン
メントとなるように調整されているので，VALUE 型のも効率的である．

2.3 浮動小数点数の表現

データがポインタである場合は，その値の下位 2 ビッ

Ruby では浮動小数点数を表現する Float オブジェ

トは 0 である．この特徴を利用して，下位 2 ビット

クトを RVALUE データ構造によって表現する．Float

が 0 で無い場合を特殊な表現手法であると認識する．

オブジェクトの RVALUE は図 4 に示す RVALUE デー

本稿では下位 2 ビットの領域をタグと呼び，VALUE 型

タによって表現されている．float_value メンバが倍の変数にポインタ以外を格納する表現を VALUE 埋

精度浮動小数点数（double 型）として Float オブジェ

め込み表現と呼び，この方式で表現されたオブジェク

クトが表現する数値自体を記録する．つまり，Float

トを VALUE 埋め込みオブジェクトと呼ぶ．VALUE

オブジェクトはメモリ管理の対象となるオブジェクト

埋め込みオブジェクトのデコード方式はそれぞれ異なである．

り，それぞれはタグによって識別される．タグによるデータ表現は動的型をもつプログラミング言語で一般的に利用される手法である．

この Float オブジェクトの表現手法には次のような問題点がある．
まず，実行効率の問題がある．数値計算プログラムに

VALUE 埋め込みオブジェクトとしては Fixnum オ

おいて Float オブジェクトは大量に，とくに一時的なブジェクト，Symbol オブジェクト，true，false，nil

オブジェクトとして生成される．この結果，RVALUE

オブジェクトがある．

の生成および初期化やガーベージコレクタの起動が頻Fixnum オブジェクトは，範囲固定の整数型である．
VALUE 型の下位 1 ビットが 1 のとき，Fixnum オブジェ
クトとして認識される．デコード方式は右へ 1 ビット
算術シフトすることで行われる．32 ビット CPU では
タグとして 1 ビット消費するため，31 ビットで表現で☆

ただし，Microsoft Windows のような，64 ビット CPU でlong 型が 32 ビットである OS 上では，互換性のために Fixnum
オブジェクトは 31 ビットで表現できる範囲の整数となる．
☆☆
この表現は，ヒープ領域の最小アドレスが 0x04 よりも大きいことを仮定している．

アプリケーションによっては 64 ビット倍精度浮動i = 0; f = 0.0
while i<30_000_000

小数点数をあきらめ，精度を落として一部をタグとし

i += 1て用いることで VALUE 埋め込み表現とすることがf += 0.1; f -= 0.1

できるが，計算精度を必要とするアプリケーションの

f += 0.1; f -= 0.1

記述が不可能となり問題である．

f += 0.1; f -= 0.1
f += 0.1; f -= 0.1
end
図 5 浮動小数点数を計算するトイプログラム

3. 64 ビット CPU 上での浮動小数点数の
VALUE 埋め込み表現の実現
現在の Ruby 処理系において，Float オブジェクトを利用する数値計算は非効率であることを示した．そこで，本章では Float オブジェクトを VALUE 埋め込
みオブジェクトとすることでメモリ管理のオーバヘッドを削減する手法を提案する．
提案する手法では，64 ビット CPU において IEEE7541) 倍精度浮動小数点数の精度を落とすことなく，
簡単なビット演算を利用してほとんどの場合にポイン
タ埋め込み表現とすることが可能であり，数値計算におけるメモリ管理のオーバヘッドを大きく削減する．
ポインタ埋め込み表現とするための基本的なアイデ
アは，現在の Ruby 処理系が実現している Fixnum オ
ブジェクトの VALUE 埋め込み表現のように，下位 1ビットを 1 としてポインタ型と区別できるようにするという単純なものである．ここで，64 ビット倍精度
図 6 トイプログラムの実行時間の内訳

浮動小数点数の精度を落とさずに，そして VALUE 埋
め込み表現への高速な符号化および double 型への復発することになり実行時間に大きな影響を与える．

号を実現する工夫が本研究での提案の骨子である．

第二に非効率なメモリ消費が挙げられる．RVALUE

3.1 倍精度浮動小数点数の VALUE 埋め込み表現

データ表現として 3 ワード割り当てられるが，double

64 ビット倍精度浮動小数点数を精度を落とさずにポ型は 32 ビット CPU の場合には 2 ワード，64 ビット

インタ埋め込み表現とするためには 63 ビットで表現

CPU では 1 ワードで表現できるため，未使用領域が可能な領域においてのみポインタ埋め込み表現とし，発生する．RVALUE へのポインタである VALUE 型を

それ以外の範囲では従来通りの RVALUE を用いた表

合わせると，1 つの Float オブジェクトを表現する

現とすればよい．

ためには 6 ワード消費することになる．C 言語では 2

そこで，63 ビットで表現可能な倍精度浮動小数点数

ワードないし 1 ワードで表現できる double 型の値をの範囲を検討し，その範囲に限って実際に埋め込み表

Ruby で利用するためには必ず 6 ワード消費すること

現にエンコード，デコードするための処理を述べる．

になり，メモリ消費量的に問題である．

3.1.1 63 ビットで表現可能な倍精度浮動小数点数の範囲の検討

問題点のうち実行効率の問題を確認するために，図5 で示すような簡単なトイプログラムを作成し，4 章

まず，IEEE754 で規定されている倍精度浮動小数で述べる環境で Ruby 1.9.0 を実行した結果から，そ

点数のフォーマットについて確認する．64 ビットの最の実行時間に占める各処理の割合を図 6 示す．なお，

下位ビットから最上位ビットまでの各ビットを bi (0 ≤この内訳は OProfile6)を利用して算出した．Calc はi ≤ 63)（ただし，b0 が最下位ビット）と置くと，b63

VM の実行や数値計算にかかる時間，Mem はメモリ

が符号ビット s，b62 ∼ b52 の 11 ビットがバイアスの管理，つまりオブジェクトの生成やガーベージコレク

かかった指数 e，b0 ∼ b51 の 52 ビットが仮数 m をションにかかる時間である．このプログラムでは単純構成し，1 ≤ e ≤ 2046 の範囲での正規化数の値 f はな数値計算の繰り返ししか行わないが，メモリ管理の(−1)s 2e−1023 m （ただし，m = 1 +ために費やす時間が全実行時間の 46%と，大きいこ

となる．

P51

b /2
i=0 i

52−i

）

とがわかる．このような単純な数値計算においてメモ

ここで，倍精度浮動小数点数が表現可能な数値の範

リ管理のオーバヘッドが大きく占めているのは問題で囲を考える．一般的に，絶対値の小さい数，および絶ある．

対値の大きな数は，その間の数よりもプログラム中での出現頻度は少ないことが期待できる．そこで，指数

VALUE rb_float_new(double dbl) {が 512 ≤ e ≤ 1535 の範囲である数値 f の場合には

VALUE v1 = BIT_DOUBLE2VALUE(dbl);

VALUE 埋め込み表現とすることを考える．この範囲

VALUE v2 = BIT_ROTL(v1, 3);外の数値は，0 以外，実験に利用した Ruby プログラ

if ((v2 + 1) & 0x02) {ムであまり出現しないことを確認してある．

return v2 | 0x01;

さて，512 < e < 1535 の範囲，つまり 0x200 ≤}e ≤ 0x5F F の範囲では，e の上位 2 ビット，数値 felse {のビット表現での b62 と b61 が b62 6= b61 という関係

if (dbl == 0) {となっている．つまり，b61 は b62 を反転したものでreturn ruby_float_zero;

表現可能である．この性質を利用すると，この範囲で}は 63 ビットで倍精度浮動小数点数が表現できること

else {になる．そこで，e がこの範囲にある数値 f を不要と

return rb_float_new_in_heap(dbl);

なった 1 ビットをタグとすることで VALUE 埋め込}

みオブジェクトとして表現し，e がこの範囲でないものは，今まで通り RVALUE データ構造を用いるよう
にする．

}
}
図 7 double 型から VALUE 型への変換ルーチン

この工夫により，絶対値が極端に大きいか小さい数
値以外は VALUE 埋め込み表現で Float オブジェク

し埋め込み表現が可能な範囲であれば，タグとして下トを表現することができる．また，その範囲以外の数

位 1 ビットを 1 にしてその値を返す．下位 1 ビット

値も，従来の手法を用いることで表現可能である．つは，b61 がローテートされた箇所なので，この情報をまり，Float オブジェクトが表現可能な数値の精度を上書きしても，b62 によって復元可能である．e が埋保っている．

め込み可能な範囲でなければ，従来通りメモリ管理の

3.1.2 ビット演算による実現手法

対象となるオブジェクトをヒープ上で獲得，初期化しVALUE 埋め込み表現を利用する範囲 512 < e <て返す．

1535 であるかどうかをチェックするためには b62 6= b61

ビットのローテートを利用することで，最下位ビッ

であればよいことがわかった．つまり，これはビットトの演算に帰着したことが高速な符号化，および後演算によって確認できる．VALUE 埋め込み表現を実に述べる復号のための工夫となっている．ローテート

現するためのタグの挿入は，この不要となった 1 ビッ

は，CPU に対応する命令があれば 1 命令で実現可能

トを利用して行う．基本的な考え方は以上だが，実際である．

に VALUE 埋め込み表現を効率的に実現するために，
ビット演算手法を工夫したのでここで紹介する．

ここで，数値 +0 が埋め込み表現可能な範囲にないことに注意が必要である（数値 +0 では e = 0 となる）．

なお，Float オブジェクトを VALUE 埋め込みオブ+0 はプログラム中に頻出するため，毎回 RVALUE

ジェクトとするために，下位 1 ビットをタグとして利データ構造の領域を確保するのは無駄である．そこで，用する．このため，従来は下位 1 ビットをタグとして+0 用の領域を事前に確保しておき，+0 だった場合に表現していた Fixnum オブジェクトなどの表現を変更

はそれを返すようにした．この工夫により +0 が出現する必要があったが，これについては次節で述べる．

するたびにメモリ確保が発生するようなことが無いよ

まずは double 型の値を VALUE 型へ符号化するルーチン rb_float_new() を図 7 に示す．

うにした．−0 も同様にサポート可能である．

rb_float_new() ル ー チ ン に よって 符 号 化 し た

まず，BIT_DOUBLE2VALUE() 関数によって double

Float オブジェクト表現から，double 型の値を取り型のビット表現を VALUE 型に取り出し v1 とする．そ出す RFLOAT_VALUE() ルーチンを図 8 に示す．まず，して，v1 を BIT_ROTL() によって 3 ビット左へロー

下位 1 ビット目が 1 であるかを調査し，そうであれテートして v2 とする．この操作により，b62 と b61 のば VALUE 埋め込み表現の Float オブジェクトとしビットが v2 の下位 2 ビットへ位置する．そして，b62てデコードする．デコードは，下位 2 ビット目と下位と b61 がそれぞれ異なるビットであるかを調べるため

1 ビット目の xor を下位 1 ビット目とすることで，そに (v2+1) & 0x02 という評価を行い，下位 2 ビット

れぞれが違う符号とするように調整し，右へ 3 ビットがそれぞれ違うか，つまり e が VALUE 埋め込み表

ローテートすることで元の double 型の値を示すビッ

現可能な範囲内であるかどうかを確認している ．も☆

☆

ここは少しわかりづらいが，評価環境では図に示したプログラ

ムがもっとも性能が良かったためこのプログラムを記載した．簡単にするためには v2 & 0x03 が 1，もしくは 2 であることを確認すれば良い．

double RFLOAT_VALUE(VALUE v) {if (v & 1) {VALUE v1 = v ^ ((v >> 1) & 1);
VALUE v2 = BIT_ROTR(v1, 3);
return BIT_VALUE2DOUBLE(v2);}else {
return RFLOAT(v)->float_value;}}
図 8 VALUE 型から double 型への変換ルーチン

ト列へ戻す．そして，BIT_VALUE2DOUBLE() によってビット列を double 型へ変換して返す．下位ビットが

図9

1 でなければ，通常の RVALUE データ構造として扱い，ポインタを辿って値を返す．

トイプログラムの実行時間の内訳の比較

ンパイラは gcc version 4.1.2 20061115 を利用した．

3.2 言語仕様への影響

比較対象とする Ruby 処理系は ruby 1.9.0 (2008-01-

Float オブジェクトの VALUE 埋め込み表現の実現

04 revision 0) [x86 64-linux]☆ ，ruby 1.8.6 (2008-01-

では，従来の Ruby 処理系との互換性を極力保つよう

04 patchlevel 5000) [x86 64-linux]，Java で実装しに設計したが，2 点変更が必要な点があったのでここ

た Ruby 処理系である JRuby 1.1b18) (java versionに紹介する．なお，この 2 点は Ruby 利用者にはほぼ”1.6.0 03” 上で実行) を用いた．Ruby 1.9.0 の VM

影響がないものである．

の最適化オプションは文献17) で述べた最適化オプショ

まずは Fixnum オブジェクトの表現を変更し，従来ンで融合操作，スタックキャッシング最適化以外を適は 63 ビットで表現できる範囲を Fixnum オブジェク

用した．評価は各プログラムを 3 回実行し，もっともトとして表現できたが，これを 61 ビットの範囲に狭短い実行時間を評価値として採用した．

めることにした．具体的には，下位 3 ビットをタグとし，下位 3 ビットが 0x02 であった場合，Fixnum でなお，本章では ruby 1.9.0 に提案手法を実装した

Ruby 処理系を 1.9.f と呼称する．

ある，というように Fixnum オブジェクトの表現を変4.2 メモリ管理オーバヘッド削減の確認

更した．しかし，整数の範囲が 61 ビットで足りない

図 5 で示したトイプログラムについて，提案手法

ことはあまりないため，問題はない．なお，この変更を実装した 1.9.f で実行したときの処理時間の割合をに伴い，true の表現も変更が必要となった．
次に，各オブジェクトにユニークに付与されるオブ

1.9.0 と 1.9.f で比較した結果を図 9 に示す．処理時間の割合は同様に OProfile6) を利用して計測した．な

ジェクト ID についての変更である．従来の Float オ

お，縦軸は実行時間である．比較を見ると，1.9.f でブジェクトはそれぞれがヒープ上で確保されるオブは明らかにメモリ管理のオーバヘッドが削減できておジェクトであるため，同一の値であってもオブジェク

り，その削減分が全体の実行時間の改善にそのまま貢ト ID が異なる可能性があった．しかし，VALUE 埋献していることが確認できた．

め込み表現可能な Float オブジェクトは同じ値であれ4.3 ベンチマークプログラムでの評価

ば必ず同じオブジェクト ID が返ることになった．し浮動小数点数を利用するベンチマークプログラム

かし，数値計算において Float オブジェクトのオブを，いくつかの Ruby のバージョンで実行して評価をジェクト ID に依存したプログラミングを行うことは行った．ベンチマークプログラムは The Computer

考えづらいので，この変更も影響はない．

Language Benchmarks Game4) にある，マンデルブ

4. 評

価

本章では提案した手法を実際に Ruby 1.9.0 に実装
し，評価した結果を示す．

4.1 評 価 環 境
評価環境は，Intel Xeon CPU E5335 2.00GHz のロ集合を求める mandel，n 体問題を解く nbody，素朴な数値計算の連続である partial-sums を利用した．
これらを評価した結果を図 10 に示す．また，この結
果を ruby 1.9.0 からの速度向上率としてまとめたものを図 11 に示す．
まず，Ruby 1.8.6 もしくは JRuby と比較して VM

プロセッサ上で行った．利用したソフトウェアは次の通りである．OS は GNU/Linux 2.6.18 x86 64，コ☆

提案手法を実装したベースもこのバージョンである．

図 10 ベンチマークプログラムの実行結果（実行時間）

図 12

他言語との比較”1.6.0 03”11) ，そして Ruby をビルドするときに利用した gcc (C) である．なお，Java と C については，
図 5 の変数 f に相当する変数を，最適化によるプログ
ラムの自体の削除を避けるために volatile として宣言しており，変数へのアクセスは毎回メモリを介して行うようにしている．そのため，最適化を制限する特
殊な C や Java プログラムとなっていることに注意されたい．

図 11 実行結果（1.9.0 との速度比較）

結果を見ると，Ruby 1.9.0 および Ruby 1.9.f はを導入した Ruby 1.9.0 は 2 倍以上高速であることを

Perl や Python といったスクリプト言語よりも高速に確認した．そして，その Ruby 1.9.0 に提案手法を適実行できていることがわかった．しかし，C や Java

用することにより，1.9.0 と比較して各ベンチマークでといったオブジェクトとして数値を扱う必要がない型

約 1.5 倍の速度向上を得ることができた．Ruby 1.8.6

付きの静的プログラミング言語のレベルにはまだ達しと Ruby 1.9.0 はメモリ管理はほぼ同等の仕組みであていないことを確認した．

る．また，JRuby も Box 化した浮動小数点数を利用している点で高速化が難しい．Ruby 1.9.0 での VM

5. 関 連 研 究化による速度向上により，Ruby 1.9.0 ではメモリ管

Ruby の浮動小数点数の利用にはメモリ管理の負荷

理のオーバヘッドがより支配的となった．メモリ管理が問題となることはよく知られている．これを回避すの負荷を削減する本手法は Ruby 1.9.0 において，従るために NArray12) という，数値しか格納すること

来の Ruby 処理系よりも有効な高速化手段といえる．

ができない配列型を実現する拡張ライブラリがある．

なお，本手法を適用するにあたり，特化命令（演算

数値しか格納しないため，メモリ管理の対象ではない

17)子などで表現される特別なメソッド用の専用命令）

ため負荷はない．NArray は，数値計算が配列上でのを VALUE 埋め込み表現の Float オブジェクトに対計算だけで済む場合は効率が良いが，数値を配列から応させ，Float オブジェクト同士の計算を高速化した．

取り出して操作を行うときにメモリ管理の負荷が発生

このとき，命令開始時に整数値のチェックを先に行うたする．

め整数演算同士の計算速度は変わらないが，文字列なプログラム中で浮動小数点数を利用する数値計算を

どの非数値オブジェクト同士の場合，Float オブジェ行う箇所が限定されている場合は，その箇所を C 言語

クトのチェックが純粋な負荷となるため速度低下が発で書き直し，拡張ライブラリとして実装することが可生した．この点は今後の課題である．

能である．また，拡張ライブラリではなく，RubyIn-

4.4 他言語との比較

line2) によって Ruby プログラム中に C 言語で問題

他の言語処理系との実行時間を比較するために，図の箇所を記述することも可能である．つまり，Ruby

5 で示したトイプログラム相当のプログラムを他のプ以外の言語を利用することで Ruby 処理系の問題を回

ログラミング言語で実装し，それらの言語処理系で実避するという手法である．しかし，これらの解決方法

行した結果を図 12 示す．比較対象とする他の言語処理

は C 言語の知識を必要とするため難易度が高く，また系は，Perl v5.8.89) ，Python 2.4.410) ，java version

Ruby だけで記述していれば起こり得ないメモリ保護

違反などの危険を招くことになる．
言語処理系での浮動小数点数を表現するオブジェク
トの軽量な表現手法としては多くの研究があるが，例
7)

えば SML#の研究が挙げられる．これは，オブジェ

クトが置かれるスタックやヒープに対して，コンパイ
ル時にメモリ上のどこにどの型が配置されるかを示す
ビットマップを用意することでオブジェクトごとに型情報を付加することを防ぐ．このような手法はコンパ
イル時に型が解析できるシステムにおいて有用である
が，Ruby ではこのような解析は困難である．
浮動小数点数の指数部の一部をタグビットに利用するというアイデアはすでに提案されている3) が，タグビットに 3 ビットを利用する点，タグの埋め込みや埋め込み可能かの判断をナイーブな計算で行っており効率が悪い．
オブジェクトの表現からヘッダ情報を取り除く一般的な手法として，64 ビット CPU の広大なアドレス空間を利用してオブジェクトの配置するアドレスと型を関連づける TVA (Typed Virtual Addressing)13) やこの手法を適用する型を選別する STVA があるが，ポインタ参照自体を取り除くものではない．また，メモリ管理の負荷は依然として発生する．

6. ま と め
本論文では 64 ビット CPU 上で倍精度浮動小数点数を表現する Float オブジェクトについて，精度を落とすことなく軽量な表現形式へ変換する手法を提案した．評価の結果，従来の Float オブジェクトの表現では数値計算において大きなオーバヘッドであったメモ
リ管理が不要となることを確認し，浮動小数点数を利用するマイクロベンチマークプログラムにおいて最大

1.54 倍の実行性能の向上を確認した．
本提案手法はビット演算のみを利用しているため，IEEE 754 の浮動小数点数を扱う言語処理系であればRuby に限らず適用可能である．また，本手法は 32
ビット CPU 上での単精度浮動小数点数でも利用でき
る．32 ビット CPU を利用する計算機環境は依然として数多く存在するため，倍精度を必要としない計算に利用することができる．

謝

辞

本論文で提案したアイデアは，Ruby コミュニティの方々，とくに三浦英樹氏に頂いた意見を参考にしています．協力してくださった方々にこの場を借りて感謝いたします．
本研究の一部は，日本学術振興会科学研究費補助金
若手研究（スタートアップ），課題番号 19800007 の助成を得て行いました．

参 考 文 献1) IEEE standard for binary floating-point arithmetic. Institute of Electrical and Electronics
Engineers, New York, 1985. Note: Standard
754–1985.
2) Ryan Davis and Zen Spider Software. Rubyinline. http://www.zenspider.com/ZSS/Products/
RubyInline/.
3) Jason Evans. Tagged unboxed floating point
numbers. http://www.canonware.com/ttt/2007/
07/tagged-unboxed-floating-point-numbers.html,
9 2007.
4) Brent Fulgham.
The computer language
bench. game. http://shootout.alioth.debian.org/.
5) David Goldberg. What every computer scientist should know about floating-point arithmetic. ACM Comput. Surv., Vol. 23, No. 1, pp.
5–48, 1991.
6) John Levon and Philippe Elie. Oprofile.
http://oprofile.sourceforge.net/.
7) Huu-Duc Nguyen and Atsushi Ohori. Compiling ml polymorphism with explicit layout
bitmap. In PPDP ’06: Proceedings of the 8th
ACM SIGPLAN symposium on Principles andpractice of declarative programming, pp. 237–
248, New York, NY, USA, 2006. ACM.
8) Charles Oliver Nutter and Thomas E Enebo.
Jruby java powered ruby implementation.
http://jruby.codehaus.org/.
9) O’Reilly Media, Inc. Perl.com: The sourcefor perl – perl development, perl conferences.
http://www.perl.com/.
10) Python Software Foundation. Python programming language. http://www.python.org/.
11) Sun Microsystems. Java テクノロジ. http://
jp.sun.com/java/.
12) Masahiro Tanaka. Numerical ruby narray.
http://narray.rubyforge.org/index.html.ja.
13) Kris Venstermans, Lieven Eeckhout, andKoen De Bosschere. Java object header elimination for reduced memory consumption in 64bit virtual machines. ACM Trans. Archit. Code
Optim., Vol. 4, No. 3, p. 17, 2007.
14) まつもとゆきひろ, 石塚圭樹. オブジェクト指向
スクリプト言語 Ruby. 株式会社アスキー, 1999.
15) まつもとゆきひろ他. オブジェクト指向スクリ
プト言語 ruby. http://www.ruby-lang.org/ja/.
16) 松本行弘. Ruby の真実. 情報処理, Vol.44, No.5,
pp. 515–521, 2003.
17) 笹田耕一, 松本行弘, 前田敦司, 並木美太郎. Ruby
用仮想マシン yarv の実装と評価. 情報処理学会
論文誌 (PRO), Vol. 47, No. SIG 2(PRO28), pp.
57–73, 2 2006.
18) 青木峰郎. Ruby ソースコード完全解説. インプ
レス, 2002.