Interactive C++: Jupyter上で対話的にC++を使う方法の紹介 [Jupyter Advent Calendar 2017]

Jupyter Advent Calendar 2017 21日目の記事です。

C++をJupyterで使う方法はいくつかあります。この記事では、僕が試したことのある以下の4つの方法について、比較しつつ紹介したいと思います。

  1. root/cling 付属のカーネル
  2. root/root 付属のカーネル
  3. xeus-cling
  4. Keno/Cxx.jl をIJuliaで使う

まとめとして、簡単に特徴などを表にまとめておきますので、選ぶ際の参考にしてください。詳細な説明は後に続きます。

cling ROOT xeus-cling Cxx.jl + IJulia
C++インタプリタ実装 C++ C++ C++ Julia + C++
(Tab) Code completion x
Cインタプリタ 1
%magics x %%cpp, %%jsroot, その他 x 2
他言語との連携 x Python, R 3 x Julia
バイナリ配布 公式リンク 公式リンク (python2系向け) condaで提供 4
オンラインデモ x rootdemo binderリンク x

共通事項

すべて、clang/llvmをC++インタプリタのベースにしています。Cxx.jl以外は、C++インタプリタであるclingをベースに、さらにその上にjupyterカーネルを実装しています。

1. cling

clingは、いわずとしれた(?)C++インタプリタ実装です。後述するROOTという data analysis framework の一部として、CERNによって開発されています。(20年くらい前の) 古くからあったCINTというC++インタプリタ実装が、clangを使って書き直された、という歴史があります。clingプロジェクトの一環としてJupyterカーネルが開発されています。

良いところ

  • clingの起動が速いのでストレスが少ない 5

イマイチなところ

  • IPythonだと使える %time のようなマジックはない
  • cling本体で良いのでは?感が否めない。cling本体のREPLを使えば、Ctrl+Rによるヒストリ検索も使えるし…

使ってみた感想まとめ

個人的には、Jupyterは可視化と組み合わせてこそ良さがあると思っているのもありますが、あえてJupyterで使う必要性を僕は感じませんでした。cling自体はとても素晴らしいのと、ノートブックとして実行結果ごとコードを保存したい、といった目的でjupyterを使う場合には、良いと思いました。

注意

#include <iostream> のあとにcode completionをしようとするとclingが落ちる、というバグがあります。Jupyterの場合はカーネルがリスタートします。

参考リンク

2. ROOT

ROOTの説明を公式ページから引用します:

A modular scientific software framework. It provides all the functionalities needed to deal with big data processing, statistical analysis, visualisation and storage. It is mainly written in C++ but integrated with other languages such as Python and R.

日本語の情報が少ない印象ですが、ROOT 講習会 2017 | 高エネルギー宇宙物理学のための ROOT 入門 – ROOT for High-Energy Astrophysics (RHEA) によると、実験系素粒子物理学では標準的なデータ解析ソフトウェア・ライブラリ群のようです。

ROOTプロジェクト自体にclingを含みますが、clingが提供するjupyterカーネルとは別で、JupyROOT というカーネルが開発されています。

良いところ

  • PythonとC++をミックスできる。%%cpp magicでC++関数を定義して、ホスト(python) 側から呼び出せる
  • %%jsroot magic により、グラフをインタラクティブに動かせる
  • IPythonで使えるmagicが使える(%timeit, %time, %load_ext等)

イマイチなところ

  • Numpyやmatplotlibなど、Pythonを用いた数値計算ではデファクトに近いツールとの連携は微妙に思いました 6。cythonのように、手軽にnumpy arrayをC++に渡す、といった方法はなさそう・・・?(あったら教えてください)
  • ROOTの(でかい)APIを覚えないと使えなさそうで、ハードルが高い
  • 公式のbinderのデモノートブック、ちょいちょいカーネルが落ちる…

使ってみた感想まとめ

Jupyterカーネルはclingのものよりも良いと思いました。PythonとC++をミックスできるのが特に良いと思います。個人的には、ROOTが機能もりもりのデカイソフトウェアなことがあまり好きになれず、使い込んでいないのですが、ROOTのAPIに慣れた人、あるいは好きになれる人には、良いと思います。

clingだと #include <iostream>のあとにcode completionで落ちる、というバグがありまたが、ROOT付属のcling (ROOT 6.10/08 をソースからビルドして使いました) ではそのバグはありませんでした。

参考リンク

3. xeus-cling

先月 11月30日に、Jupyter blog で紹介 されたカーネルです。名前の通りclingをベースにしています。C++インタプリタとしては機能的にcling付属カーネルと同じですが、xeus というJupyter kernel protocolのC++実装をベースにしている点が異なります。

良いところ

  • condaでパッケージとして提供されているので、インストールが楽。clang/clingも併せてインストールしてくれます
  • 同じ開発元が、xplot という可視化ライブラリを提供している(ただしalphaバージョン)
  • 標準ライブラリのヘルプが ? コマンドで確認できます (例. ?std::vector)

イマイチなところ

  • 外部ライブラリをロードしようとしたら動きませんでした(なので プルリク 投げました(が、いい方法ではなかったようでcloseされました
  • %timeit の実装があったので試してみましたが、エラーが出て動きませんでした

使ってみた感想まとめ

少しalphaバージョンの印象を受けました。xplotなど周辺ツールへの期待がありますが、個人的にはmatplotlib等pythonの可視化ツールでいいのでは…という気持ちになりました。

参考リンク

4. Cxx.jl + IJulia.jl

Cxx.jlは、clangをベースにしたJuliaのC++インタフェースです。JuliaにはIJuliaというJupyterカーネルの実装があるので、IJuliaとCxx.jlを使えば、Jupyter上でC++を使うことができます。過去にCxx.jlに関する記事をいくつか書きましたので、そのリンクを貼っておきます。

良いところ

  • JuliaとC++をミックスできます。過去記事に書きましたが、例えばC++関数内でJuliaのプログレスバーを使ったりできます
  • C++インタプリタとCインタプリタを切り替えられます
  • icxxcxx マクロで、それぞれローカル/グローバルスコープを切り替えられます。
  • Juliaの配列をC++に渡すのは非常に簡単にできます。例を以下に示します
C++ > #include <iostream>
true

julia> cxx"""
       template <class T>
       void f(T x, int n) {
           for (int i = 0; i < n; ++i) {
               std::cout << x[i] << std::endl;
           }
       }""";

julia> x = rand(5)
10-element Array{Float64,1}:
 0.593086
 0.736548
 0.344246
 0.390799
 0.226175

julia> icxx"f($(pointer(x)), $(length(x)));"
0.593086
0.736548
0.344246
0.390799
0.226175

イマイチなところ

  • Cxxパッケージを読み込むのに多少時間がかかります。僕の環境では(プリコンパイルされた状態で)2.5秒程度でした
  • (Tab) Code completionは実装されていません #61
  • icxx or cxx で囲まないといけず、syntax highlightはされません

使ってみた感想まとめ

僕は一年以上Cxx.jlを使っているので、バイアスも入っていると思いますが、かなり使いやすいと思います。パッケージのロードに時間がかかるのは、何度もカーネルやjuliaを再起動したりしなければ、まったく気になりません。IJuliaの設計上の理由 により、magicはありませんが、例えば %time@time マクロで十分であり、不便に感じません。

参考リンク

まとめ

  • C++と他言語のやりとりのスムースさの観点から、やはり僕は対話環境でC++を使うならCxx.jlが最高だと思いました。Cxx + JuliaのREPLも便利ですが、Cxx + IJuliaも良いと思います。
  • ただし、C++単体でしか使わない、ということであれば、cling or xeus-clingが良いと思います。ただし xeus-clingは、前述の通り外部ライブラリを読みこもうとするとエラーになる問題があったので、外部ライブラリを読み込んで使用したい場合はパッチ (xeus-cling/#94) を当てた方がよいかもしれません
  • xeus-clingには、Jupyterブログにのっていたのでどんなものかと思って試してみましたが、周辺ツール含め思ってたよりalpha版のようでした。また、他と比べての機能的な優位性はあまり感じませんでした。ただし、condaパッケージとして提供されているので、敷居が一番低いのは嬉しいですね
  • ROOTのjupyter kernelは、C++とpythonをミックスできるのが特に良く、素晴らしいと思いました。また %%cpp magicの他にも、ipythonで使える %timeit などのmagicも使えるのは、ユーザにとっては嬉しいです。Cxx.jlを除けば、ROOTのカーネルが一番良いと思いました。

参考


  1. clangをベースにしているので原理的には可能だと思いますが、少なくともjupyterカーネルとしてはありません ↩︎

  2. Juliaのmacroを使えばよい、というスタンスで、提供していません。 参考リンク ↩︎

  3. 公式ホームページ より引用: It is mainly written in C++ but integrated with other languages such as Python and R. ↩︎

  4. linux向け ↩︎

  5. Cxx.jlだと、パッケージのコンパイルに10秒かかる、とか過去にありました。最近は改善されていますが ↩︎

  6. https://github.com/rootpy/rootpy ライブラリはありますが、結局このライブラリのAPIを覚えないといけないという…はい… ↩︎

Ryuichi Yamamoto
Ryuichi Yamamoto
Engineer/Researcher

I am a software engineer / researcher passionate about speech synthesis. I love to write code and enjoy open-source collaboration on GitHub. Please feel free to reach out on Twitter and GitHub.

Related