ククログ

株式会社クリアコード > ククログ > 名古屋Ruby会議03:Apache ArrowのRubyバインディングをGObject Introspectionで #nagoyark03

名古屋Ruby会議03:Apache ArrowのRubyバインディングをGObject Introspectionで #nagoyark03

2017年2月11日に名古屋Ruby会議03大須演芸場で開催されました。ここで咳さんの並列処理啓蒙活動話の前座の1人として話してきました。内容は、Apache ArrowGObject IntrospectionRroongaを活用すれば自然言語のデータ分析の一部でRubyを活用できるよ!、です。

関連リンク:

リポジトリーには今回のスライド内で使ったスクリプトも入っています。

内容

当初は以下にいろいろまとめていた通り、Apache Arrow・GObject Introspectionはどんな特徴でどういう仕組みでそれを実現しているかといったことも説明するつもりでした。

ただ、内容をまとめていく過程で、特徴や仕組みの説明が多いと大須演芸場で話すには勢いが足りないと判断しました。その結果、詳細をもろもろ省略したストーリーベースの内容にしました。そのため、↑の内容はほぼ使っていません。

ストーリーベースの内容にしたことで「あぁ、たしかにデータ分析の一部でRubyを使えるかも」という雰囲気は伝わりやすくなったはず(どうだったでしょうか?)ですが、詳細の説明を省略したので詳細が気になったまま終わった人もいるかもしれません。そんな人たち向けに詳細がわかる追加情報を紹介します。

Apache ArrowとApache Parquet

まず、Apache ArrowとApache Parquetの連携についてです。両者はどちらもカラムストアのデータについて扱いますが、Apache Arrowはメモリー上での扱い、Aapache Parquetはストレージ上での扱いという違いがあります。この違いのためにトレードオフのバランスが変わっています。詳細はThe future of column-oriented data processing with Arrow and Parquetを見てください。2016年11月にニューヨークで開催されたDataEngConf NYCでのApache Parquetの作者の発表資料です。

ざっくりとまとめると次の通りです。

  • Apache Parquetはストレージ上でのカラムストアのデータの扱いなので、次の傾向がある。

    • CPUを活用するよりもI/Oを減らすほうが重要(たとえば、データを圧縮するとI/Oは減る一方CPU負荷は増えてしまうが、I/Oを減らしたいので圧縮をがんばる)

    • シーケンシャルアクセスが多い

  • Apache Arrowはメモリー上でのカラムストアのデータの扱いなので、次の傾向がある。

    • I/Oを減らすよりもCPUを活用するほうが重要(たとえば、CPUキャッシュミスが少なくなるようなデータ配置にする)

    • シーケンシャルアクセスもあるしランダムアクセスもある

データの配置や高速化の工夫なども前述の発表資料で説明しているので興味のある人は発表資料も確認してください。

Apache ArrowとApache Parquetは連携できます。具体的に言うと、Apache ParquetのC++実装にはApache Arrowのデータを読み書きできる機能があります。これを使うとApache ParquetのデータをApache Arrowのデータとして扱うことができます。

GObject Introspection

GObject Introspectionに関する情報は次の記事を参考にしてください。

GObject Introspectionに対応するとバインディングを書かなくてもCライブラリーのテストをRubyで書けるようになります。Cライブラリーの開発を捗らせるためにGObject Introspectionに対応させるというのもアリです。(これも当初は話したかったけど省略した話題です。)

GObject IntrospectionのRubyバインディングであるgobject-introspection gemについてはここで少し補足します。

話の中で、GI.loadした後、よりRubyっぽいAPIになるように一手間かけるとグッと使いやすくなると説明しました。当日は次のようにエイリアスを使う方法だけを紹介したのですが、別の方法もあってそれを紹介することをすっかり忘れていました。

require "gi"
Arrow = GI.load("Arrow")
class Arrow::Array
  def [](i)
    get_value(i)
  end
end

実はGObjectIntrospection::Loaderには定義するメソッド名を変える機能があります。上述のケースではエイリアスを作るのではなく、最初からget_value[]として定義するとよいです。

class Arrow::Loader < GObjectIntrospection::Loader
  private
  def rubyish_method_name(function_info, options={})
    # 引数が1つで、メソッド名がget_valueならメソッド名を[]にする
    if function_info.n_in_args == 1 and function_info.name == "get_value"
      "[]"
    else
      super
    end
  end
end

このようにGObjectIntrospection::Loaderをカスタマイズするやり方には次のメリットがあります。

  • 余計なメソッドを増やさない(今回のケースではget_value

  • 新しく同じパターンのメソッドが増えてもエイリアスを追加する必要がない(たとえば、Arrow::Array以外にget_value(i)なメソッドが増えてもバインディングを変更する必要がない)

この実装はRed Arrow(RArrowから名前を変更、由来はRubyは赤いからというのと西武新宿線の特急列車)にあります。open {|io| ...}を実現する方法も面白いので、GObject Introspectionが気になってきた方はぜひ実装も見てみてください。

まとめ

名古屋Ruby会議03で「Apache ArrowとGObject IntrospectionとRroongaを使って自然言語のデータ分析の一部でRubyを活用する」という話をしました。(使い方を間違っていましたが)はじめて小拍子を使ったり、はじめてマクラの後に羽織(?)を脱いだりできて、楽しかったです。貴重な経験になりました。声をかけてもらってありがとうございます。名古屋のみなさん(名古屋外からの参加の方も多かったですが)に楽しんでもらえていたなら、とてもうれしいことです。

今回の話では詳細をもろもろ省略しましたが、そのあたりに興味のある方がいたらぜひお声がけください。

また、クリアコードと一緒にRubyでデータ分析できる環境を整備していきたい!という方はぜひお問い合わせください。