Rでforループを書くと非常に遅いことは知られており、同じループでもC言語で書くとそれなりに速くなります。RからC言語のライブラリを呼ぶ方法をいくつか紹介したいと思います。なんともまぁ、マニアックな話題ですこと。言われる前に自らツッコんでおきます(笑)。
Rについて
Rについてそういえば説明しておりませんでしたが、統計解析のためのパッケージソフトウェアです。公式サイトはこちらです。有名なSASやSPSSと違ってオープンソースであり、どこでもフリーで利用でき、またユーザーと開発者が近いために世界中からパッケージが新しく開発されております。特に新しい統計解析手法を開発した研究者自らが手法をパッケージ化したりすることもしばしばであるため、最新の手法が簡単に利用可能だったりします。逆にいいますと、R本体に含まれているstats、graphics、baseなどのパッケージはR Coreメンバーによって管理されておりますが、ユーザーが作ったパッケージは最低限の動作チェックのみで、他のパッケージとの相性などのチェックはされておりません。なので、色々なパッケージを使い熟すには、ソースを読んだりすることが場合によっては必要だったりします。それから作成する図表が綺麗という特徴もあります。日本語で最も情報が充実しているサイトは岡田先生の管理されているサイトだと思います。
Rの機能を拡張するのがパッケージであり、その数の上昇具合はスラドでも話題になっていたりします。パッケージの中には、R言語の範疇を越えてC/C++言語やFortranなどで書かれているものもあります。特にRでforループを書くと非常に遅いことは知られており、そのためにapply系関数が薦められたりしておりますが、同じループでもC言語で書くとそれなりに速くなります。パッケージとして外部ライブラリを作ろうとすると面倒ではありますが、手元でC言語のライブラリを呼ぶだけならもう少し簡単にできます。その方法をいくつか紹介したいと思います。
Rで拡張プログラムを作る際レファレンスとしては、Rをインストールすると一緒に入れられるPDFを見るのが一番です。Windows版のRGuiですと、ヘルプメニューの中の、マニュアル(PDF)からWriting R Extensionsを選択することで開くことができます。
Rtoolsを用いる方法
一応基本から先に説明したいと思います。最近ではRcppパッケージなどを使えばもっと簡単にできますが、今回はこちらから説明します。Rtoolsはこちらからダウンロードすることができます。これを入れるだけで、開発環境が入ります。インストール後、確かWindowsの環境変数の設定からパスをRのインストールされたディレクトリのbinに通しておく必要があったと思います(例「C:\Program Files\R\R-X.X.X\bin」など)。正しくインストールされていれば、コマンドプロンプトを起動して「R CMD SHLIB」と入力すると、「make: Nothing to be done for all」のような表示が出るはずです。ここまでできれば、いつものごとく、簡単なサンプルプログラム(tmp.cc)です。
#include <Rdefines.h> extern "C" SEXP hoge(SEXP arg) { Rprintf("Hello Hoge!\n"); return R_NilValue; }
相変わらずHogeです(笑)。Rprintf関数は、通常のprintf関数とほぼ使い方は同じであり、Rのコンソール上に文字列を表示する関数です。RはSを真似て作られており、SEXPはS EXPressionの略だったと思います(最初、別のものを想像してしまったのは私だけでないはず…orz)。中身はポインタで、このポインタを通してRと外部ライブラリでRオブジェクトのやり取りをします。ここでは引数を一つ受け取りますが、特に使わずにまたHoge!と叫んで、NULLを返す、という関数です。
このファイルを置いたところで
R CMD SHLIB tmp.cc
を実行すると、tmp.dllが作られます。たったこれだけです。素晴しいですね(後の記事で別の環境で同じことをやって苦労をしたいと思います)。これをRからさっそく使ってみましょう。Rを起動し「getwd()」を実行すると現在のディレクトリが表示されます。tmp.dllと違う場合、「setwd(path)」でpathにdllがある場所を指定して実行します。この場合のpathの指定は「“c:/user/hoge/”」のように文字列として二重引用符で囲み、なおかつ区切りは円マークやバックスラッシュではなく「”/”」を指定します。「dir()」で現在のディレクトリにtmp.dllがあることを確認します。DLLを
dyn.load("tmp.dll")
とすることでロードします。正しくロードできていれば、tmp.cc内にあるhoge関数がロードされたことが以下で確認できます。
is.loaded("hoge")
の実行結果がFALSEならば正しくロードされていないことになります。extern “C”の付け忘れなどを確認してください。TRUEが表示され、ロードされたならば実行してみましょう。
.Call("hoge", 1)
とすれば実行することができます。.Call関数は、最初に関数名の文字列を引数に取り、それ以降はその関数に与える引数を連ねていきます。一つの引数を取るので、数値の1を与えておりますが、中では一切使わずにただHoge!と叫んでNULLを返してきます。Rの関数からこの関数を呼んでみたいと思います。
SayPassword <- function(){ invisible(.Call("hoge", 1)) }
是非パスワードを言わせてあげてください…。
コメント