C++製のxtensorで多次元配列を扱ってみる

github.com

今回はこのxtensorというC++で多次元配列を扱うライブラリを使う。
このxtensorはnumpyにinspireされて作られているとのこと。
numpyに関してはPythonから使うのだがxtensorはC++で作られているとのことで、各言語でバインディングを用意してあげればその言語で多次元配列の演算とかが出来るようになる。
現状だとPythonとかRとかJuliaにはあるみたいです。

準備

まずはxtensor自体はC++で書かれているのでC++コンパイル出来る状態でないといけない。
C++14をサポートしているので、今回はGCC6.1からC++14が標準になったということで今が最新の7.1を使用することにした。

$ add-apt-repository ppa:ubuntu-toolchain-r/test
$ apt-get update
$ apt-get install g++-7

xtensor自体のインストールに関してはこちらのリポジトリのREADME.mdにもあるようにcondaがmakeでインストールをする。
今回はcondaを使用することにした。

$ wget https://repo.continuum.io/archive/Anaconda3-4.4.0-Linux-x86_64.sh
$ bash Anaconda3-4.4.0-Linux-x86_64.sh -b

これでcondaが入ったので conda install -c conda-forge xtensor でxtensorをインストールする。
今回はrootユーザーにてcondaをインストールしてディレクトリはデフォルトのホームディレクトリを指定したので、xtensorのインクルードファイルは/root/anaconda3/include/配下のxtensorに入っている。

最初から入っているg++を入れ直したりとかわりと面倒だったので今後のためにもxtensorが動かせる環境をdocker imageに作成をしておいた。

https://hub.docker.com/r/hatappi/xtensor/

この後の動かしてみたに関しては今回作成したdocker imageを元にして検証している。

いくつか動かしてみた

多次元配列同士の足し算

#include <iostream>
#include "xtensor/xarray.hpp"
#include "xtensor/xio.hpp"

int main() {
  xt::xarray<double> arr1
    {{1, 2, 3},
     {4, 5, 6},
     {7, 8, 9}};

  xt::xarray<double> arr2
    {{1, 2, 3},
     {4, 5, 6},
     {7, 8, 9}};;

  xt::xarray<double> res = arr1 + arr2;

  std::cout << res;
  std::cout << "\n";
  return 0;
}

実行する

# -I でxtensorが入っているインクルードディレクトリを指定する
# 指定しないとxtensorないよってコンパイル時にいわれる
$ g++-7 -I /root/anaconda3/include -o test test.cpp
$ ./test
{{  2.,   4.,   6.},
 {  8.,  10.,  12.},
 { 14.,  16.,  18.}}

おぉーちゃんと計算されてる

sumとかもある

#include <iostream>
#include "xtensor/xarray.hpp"
#include "xtensor/xio.hpp"

int main() {
  xt::xarray<double> arr
    {{1, 2, 3},
     {4, 5, 6},
     {7, 8, 9}};

  std::cout << "ALL SUM\n";
  xt::xarray<double> all_sum = xt::sum(arr);
  std::cout << all_sum;

  std::cout << "\nROW SUM\n";
  xt::xarray<double> row_sum = xt::sum(arr, {0});
  std::cout << row_sum;

  std::cout << "\nCOLUMN SUM\n";
  xt::xarray<double> column_sum = xt::sum(arr, {1});
  std::cout << column_sum;

  std::cout << "\n";
  return 0;
}

実行

$ g++-7 -I /root/anaconda3/include -o test test.cpp
$ ./test
ALL SUM
 45.
ROW SUM
{ 12.,  15.,  18.}
COLUMN SUM
{  6.,  15.,  24.}

この他にもnumpyでいう~~はあるがそれはthe-numpy-to-xtensor-cheat-sheetを見ると分かります。

最後に

今回はとりあえず動かしてみた