Apache Arrow東京ミートアップ2018で「RとApache Arrow」について話してきました

ほんとに私でいいんだろうか...という気持ちでしたが、Apache Arrow東京ミートアップ2018でRとApache Arrowの現状と未来の妄想について話してきました。 色んな分野の話を聞けてとても勉強になりました。

たぶんこのブログを読むのはR界隈の人だと思うので、興味を持ってもらえそうなトピックだけかいつまんで。 r-wakalangに#arrowチャンネルをつくったので、R界隈のApache Arrowの情報交換とかはそこでやっていきましょうー。

R(とJuliaも?)が他の言語と違うところ

まず、Rには標準のデータ構造をApache Arrowで置き換えるモチベーションはあまりないです。

たとえばPythonだと、Apache Arrowの中心人物の一人であるWes McKinneyはNumPyの欠損値とカテゴリ値のサポートが不十分なことを Apache Arrowを推進するモチベーションのひとつとして挙げています(このへんはsinhrksさんのスライドを見ましょう)。

一方で、Rには欠損値もカテゴリ値もすでにあります(Juliaには遅いとdisられたりするけど)。 既存のデータ構造を置き換えるのはそれほど魅力的ではなく、開発コストを考えると及び腰になるのもまあわかるなあ、というところです。

とはいえRはRだけでやっていけるほど強くはない

だがしかし。

上で「それほど魅力的ではない」と書いたのは、R単体で考えた場合です。 Rは、他のソフトウェアとのやりとりが多い言語なので、そこにArrowを推し進めるモチベーションがあると思っています。

具体的に例を挙げると、データベースとか。同じ日に某所で「SQL最高!」という発表があったことは知っていますが、 データベースに接続してSQLを投げて結果を取ってくるだけのことに、人類はつまづきまくります。つらい。何とかしたい。というのが私のスライドで一番言いたいことでした。

ここで妄想したような大統一Arrow Flight時代はどうやらそんなに簡単には来なさそうですけど(さすがにSQLの代わりにGandivaの計算グラフを投げられるようにはならないのでは?という指摘を受けました。適当な図を描いてしまってすみません...)、 データベースコネクタに悩まされなくなるのは大きいと思っています。

f:id:yutannihilation:20181208235621p:plain
大統一Arrow Flight時代の妄想の図

ALTREP

ALTREPは、通常のRのオブジェクトとは異なるデータを通常のRのオブジェクトのように見せるための仕組みで、R 3.5.0から導入されたものです。 例えば、以下の1:1e6はALTREPの仕組みを使う特殊なデータ構造になっています。 通常のベクトルのようにインデックスを指定して要素を取り出したりできますが、必要になるまでメモリ上には展開されないためオブジェクトのサイズはほとんどありません。

x <- 1:1e6

lobstr::obj_size(x)
#> 680 B

.Internal(inspect(x))
#> @0x000002236aec1388 13 INTSXP g0c0 [MARK,NAM(3)]  1 : 1000000 (compact)

x[100] 
#> [1] 100

適当なインデックスに数値を代入すると、メモリ上に展開されるので一気にサイズが増えます。

x[100] <- 1L

lobstr::obj_size(x)
#> 4,000,048 B

Internal(inspect(x))
#> @0x00007ff43f4e0010 13 INTSXP g0c7 [NAM(3)] (len=1000000, tl=0) 1,2,3,4,5,...

しかし、ふつうにRを使っていればこのような内部構造の違いを意識することはありません。 違いはALTREPによって隠蔽され、通常のRのオブジェクトとまったく同じように扱えるからです。

Apache Arrowに対しても、Arrow Flightで受け取ったArrow形式のデータをそのままメモリ上に保持して、 ALTREPによって透過的にアクセスすることができるようになると思います。

(とはいえ、data.tableであったトラブルとかを見てると、C++からALTREPを扱うには注意が必要そうで、 様々なライブラリを対応させるにはそれなりの労力が必要かもしれません)

最後に

冒頭にも書いたように、r-wakalangに#arrowチャンネルをつくったので情報交換していきましょう!