C ++用のNumPyスタイルの配列?


83

スライス、ベクトル化された操作、要素ごとのコンテンツの加算と減算などをサポートするNumPyのような配列を持つC ++(またはC)ライブラリはありますか?



1
私の知る限り、numpyはLAPACKを使用しています。それはFortranで書かれていますが、利用可能なc ++バインディングがあります。ただし、どちらも使用したことはありません。
Voo 2012年

ArmaNpyと呼ばれるNumPyへの最近のC ++インターフェースがあります。
mtall 2013年

1
コメントにBoost.MultiArrayがまだ表示れていません
Dmitry Ledentsov 2014

Pythonを埋め込んで、実際にnumpyを使用してみると、C / C ++ライブラリを使用するよりも時間がかかりますが、新しいライブラリを学習する必要がないという利点があります。
ケビン

回答:


57

ここにあなたのニーズに合うかもしれないいくつかのフリーソフトウェアがあります。

  1. GNU科学ライブラリは、このようにC言語で書かれたGPLソフトウェアです、それはCのようなプログラミング(ポインタなど)の割り当てと方法を持っています。GSLwrapまだGSLを使用している間、あなたは、プログラミングのC ++方法を持つことができます。GSLにはBLAS実装がありますが、さらにパフォーマンスが必要な場合は、デフォルトのCBLASの代わりにATLASを使用できます。

  2. ブースト/ uBLASのライブラリはC ++で書かれており、ブーストパッケージとして配布、BSLライブラリです。これは、BLAS標準を実装するC ++の方法です。uBLASにはいくつかの線形代数関数が付属しており、ATLASへの実験的な結合があります。

  3. 固有のMPL2ライセンス(バージョン3.1.1から開始)またはLGPL3 / GPL2(旧バージョン)の下で配布、C ++で書かれた線形代数ライブラリです。これはC ++のプログラミング方法ですが、他の2つよりも統合されています(より多くのアルゴリズムとデータ構造が利用可能です)。Eigenは、デファクトスタンダードのBLAS APIに準拠していませんが、上記のBLAS実装より高速であると主張しています。Eigenは、並列実装にあまり力を入れていないようです。

  4. アルマジロは、C ++用のLGPL3ライブラリです。LAPACK(numpyが使用するライブラリ)のバインディングがあります。再帰的なテンプレートとテンプレートメタプログラミングを使用します。これは良い点です(他のライブラリもそれを行っているかどうかはわかりませんか?)。

  5. xtensorは、BSDライセンスのC ++ライブラリです。NumPyと非常によく似たC ++ APIを提供します。チートシートについては、https://xtensor.readthedocs.io/en/latest/numpy.htmlを参照してください

これらの選択肢は、データ構造と基本的な線形代数を取得したいだけの場合に非常に役立ちます。スタイル、ライセンス、またはsysadminの課題(LAPACKのような大きなライブラリのインストールは難しい場合があります)に関する好みに応じて、ニーズに最適なものを選択できます。


15
信じられないかもしれませんが、私の答えは、数か月前の私自身の検索の結果です。自分の選択に役立つ情報を収集することには、ある程度の関心があると信じていました。いくつかの情報を回答全体に分散させる方がよいかどうかはわかりません。効率よりも倫理に関心があると感じた場合でも、全員を賛成することができます。
nojhan 2012年

19
悲しいことに、これらのどれも、numpy配列ほど一般的で便利なものを提供していません。Numpy配列は任意の次元であり、a[:4,::-1,:,19] = b[None,-5:,None]またはa[a>5]=0同様のものをサポートし、配列およびインデックス操作関数の膨大なセットを利用できます。いつか誰かがC ++用にそのようなものを作ってくれることを本当に望んでいます。
amaurea 2014年

2
OpenCVには、任意の次元サイズを持つことができるMatrixタイプもあります。列/行の範囲(のa.colRange(4,7).rowRange(4,8)場合a[4:7,4,8])および条件マスク(のa.setTo(cv::Scalar(0), a>5)場合a[a>5]=0
xaedes 2016

3
@amaureaは、上記のすべてを可能にする以下のxtensorの回答を確認してください。
Quant 2017年

1
最近のプロジェクトでEigenを使用する必要がありました。効率的であるように見えますが、構文は絶対にひどいものであると言わざるを得ません。利用可能なその驚くべきPythonスライシング構文はありません。たとえば、1Dベクトルxがあり、最初のn個の要素を操作する場合は、x.head(n)を使用する必要があります。xの任意のスライスを操作することについても尋ねないでください。それを行うには、古き良きforループが必要です。これは、私が挙げることができる多くの不格好で不便な例の1つにすぎません。
アレックス

53

xtensorを試してみてください。(NumPyからXtensorへのチートシートを参照してください)。

xtensorは、多次元配列式を使用した数値解析を目的としたC ++ライブラリです。

xtensorは提供します

  • numpyスタイルの放送を可能にする拡張可能な表現システム。
  • C ++標準ライブラリのイディオムに従ったAPI。
  • 配列式を操作し、xtensorに基づいて構築するためのツール。

2次元配列を初期化し、その行の1つと1次元配列の合計を計算します。

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

xt::xarray<double> arr1
  {{1.0, 2.0, 3.0},
   {2.0, 5.0, 7.0},
   {2.0, 5.0, 7.0}};

xt::xarray<double> arr2
  {5.0, 6.0, 7.0};

xt::xarray<double> res = xt::view(arr1, 1) + arr2;

std::cout << res;

出力

{7, 11, 14}

1次元配列を初期化し、インプレースで再形成します。

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

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

arr.reshape({3, 3});

std::cout << arr;

出力

{{1, 2, 3},
 {4, 5, 6},
 {7, 8, 9}}

2
@Llamageddonこれが選択された答えになると思いますか?
クワント

7

DyNDは、とりわけ、C ++用のNumPyのようなライブラリになるように設計されています。ブロードキャスト、算術演算子、スライスなどはすべて正常に機能します。一方で、それはまだ非常にです実験的であり、多くの機能はまだ実装されていません。

DyND配列を使用したC ++でのdeCasteljauアルゴリズムの簡単な実装を次に示します。

#include <iostream>
#include <dynd/array.hpp>

using namespace dynd;

nd::array decasteljau(nd::array a, double t){
    size_t e = a.get_dim_size();
    for(size_t i=0; i < e-1; i++){
        a = (1.-t) * a(irange()<(e-i-1)) + t * a(0<irange());
    }
    return a;
}

int main(){
    nd::array a = {1., 2., 2., -1.};
    std::cout << decasteljau(a, .25) << std::endl;
}

ブログ記事を書きました少し前に、Fortran 90、C ++のDyND、PythonのNumPyの構文の例と並べて比較し。

免責事項:私は現在のDyND開発者の1人です。


3

Eigenは優れた線形代数ライブラリです。

http://eigen.tuxfamily.org/index.php?title=Main_Page

ヘッダーのみのライブラリなので、インストールは非常に簡単です。十分に最適化されたコードを生成するためにテンプレートに依存しています。行列演算を自動的にベクトル化します。

また、たとえば2つの行列間の「要素ごとの乗算」などの係数に関する演算も完全にサポートします。それはあなたが必要なものですか?


3
しかし、固有値の構文はかなりひどいです。Numpyに見られるようなスムーズなスライス構文はありません。そして、それは一般的なn次元配列ライブラリではなく、1Dベクトルと2D行列専用です。1D配列用のVectorXdと2D配列用のMatrixXdがあるという事実は、すでに私を撃退しています。
アレックス

2

Blitz ++は任意の数の軸を持つ配列をサポートしますが、Armadilloは最大3つ(ベクトル、行列、および立方体)のみをサポートします。Eigenは、ベクトルと行列のみをサポートします(立方体はサポートしません)。欠点は、Blitz ++には、基本的な入力単位の演算とテンソルの縮約以外の線形代数関数がないことです。開発はかなり前に遅くなっているようですが、おそらくそれはライブラリがそれを実行し、多くの変更を加える必要がないためです。


2

xtensorは良いのですが、インターフェイスをできるだけシンプルに保ちながら、c ++ 20を使ったおもちゃのプロジェクトとして自分でミニライブラリを書くことになりました。ここにあります:https//github.com/gbalduzz/NDArray

コード例:

using namespace nd;
NDArray<int, 2> m(3, 3); // 3x3 matrix
m = 2; // assign 2 to all
m(-1, all) = 1; // assign 1 to the last row.

auto tile = m(range{1, end}, range{1, end}); // 2x2 tile
std::sort(tile.begin(), tile.end());

std::cout << m; // prints [[2, 2, 2], [2, 1, 1], [1, 2, 2]]

複数の演算をまとめて折りたたむ派手な算術演算子はまだ提供されていませんが、任意のラムダを同じ形状のテンソルのセットにブロードキャストしたり、遅延評価された算術演算子を使用したりできます。

インターフェースについてどう思いますか、他のオプションとどのように比較するか、そしてこれに希望があれば、どのような操作を実装してほしいかを教えてください。

無料ライセンスと依存関係なし!

補遺:xtensorを適切にコンパイルして実行することができました。その結果、ビューを反復処理するとライブラリが大幅に高速になります(2〜3倍)。


1

VIGRAには、優れたN次元配列の実装が含まれています。

http://ukoethe.github.io/vigra/doc/vigra/Tutorial.html

私はそれを広く使用していますが、非常にシンプルで効果的です。また、ヘッダーのみであるため、開発環境に非常に簡単に統合できます。これは、APIの観点からNumPyを使用するのに最も近いものです。

主な欠点は、他の製品ほど広く使用されていないため、オンラインで多くのヘルプを見つけることができないことです。それ、そしてそれは厄介な名前です(それを検索してみてください!)



1

これは古い質問です。まだ答えたくなった。思考は多くの人、特にC ++でコーディングするpydevsに役立つかもしれません。

すでにpythonnumpyを使用している場合は、NumCppが最適です。構文は最小限であり、pynumpyと同様の関数またはメソッドがあります。

readmeドキュメントの比較部分も非常にクールです。

NumCpp

nc::NdArray<int> arr = {{4, 2}, {9, 4}, {5, 6}};
arr.reshape(5, 3);
arr.astype<double>();

0

Eigenは、線形代数(行列、ベクトルなど)のテンプレートライブラリです。ヘッダーのみで無料で使用できます(LGPL)。


0

画像処理やニューラルネットワークに多次元配列(numpyなど)を使用する場合は、 OpenCV cv::Matの画像処理アルゴリズムと一緒に。行列演算のみに使用したい場合は、それぞれのopencvモジュールをコンパイルしてサイズを縮小し、OpenCVライブラリを小さくする必要があります。

cv::Mat(行列)は、RGB、HSVまたはグレースケール画像、実数値または複素数値のベクトル、その他の行列など、さまざまなタイプのデータを格納するために使用できるn次元配列です。

マットには次の情報が含まれています:width, height, type, channels, data, flags, datastart, dataendなど。

行列操作にはいくつかの方法があります。ボーナスは、CUDAコアだけでなく作成することもできますcv::cuda::GpuMat

10行20列の行列を作成し、CV_32FC3と入力するとします。

int R = 10, C = 20;
Mat m1; 
m1.create(R, C, CV_32FC3); //creates empty matrix

Mat m2(cv::Size(R, C), CV_32FC3); // creates a matrix with R rows, C columns with data type T where R and C are integers, 

Mat m3(R, C, CV_32FC3); // same as m2

ボーナス:

行列演算だけのために、小さくてコンパクトなopencvライブラリをコンパイルします。一度の方法は、この記事で述べたようなものです。

または

次のcmakeコマンドを使用してopencvソースコードをコンパイルします。

$ git clone https://github.com/opencv/opencv.git
$ cd opencv
$ git checkout <version you want to checkout>
$ mkdir build
$ cd build
$ cmake -D WITH_CUDA=OFF -D WITH_MATLAB=OFF -D BUILD_ANDROID_EXAMPLES=OFF -D BUILD_DOCS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_TESTS=OFF -DANDROID_STL=c++_shared -DBUILD_SHARED_LIBS=ON -D BUILD_opencv_objdetect=OFF -D BUILD_opencv_video=OFF -D BUILD_opencv_videoio=OFF -D BUILD_opencv_features2d=OFF -D BUILD_opencv_flann=OFF -D BUILD_opencv_highgui=OFF -D BUILD_opencv_ml=OFF -D BUILD_opencv_photo=OFF -D BUILD_opencv_python=OFF -D BUILD_opencv_shape=OFF -D BUILD_opencv_stitching=OFF -D BUILD_opencv_superres=OFF -D BUILD_opencv_ts=OFF -D BUILD_opencv_videostab=OFF -D BUILD_opencv_dnn=OFF -D BUILD_opencv_imgproc=OFF ..
$ make -j $nproc
$ sudo make install

この例を試してください:

 #include "opencv2/core.hpp"
 #include<iostream>

 int main()
 {
     std::cout << "OpenCV Version " << CV_VERSION << std::endl;

     int R = 2, C = 4;
     cv::Mat m1;
     m1.create(R, C, CV_32FC1); //creates empty matrix

     std::cout << "My Mat : \n" << m1 << std::endl;
 }

次のコマンドでコードをコンパイルします。

$ g++ -std=c++11 opencv_mat.cc -o opencv_mat `pkg-config --libs opencv` `pkg-config --cflags opencv`

実行可能ファイルを実行します。

$ ./opencv_mat

OpenCV Version 3.4.2
My Mat :
[0, 0, 0, 0;
 0, 0, 0, 0]


-1

一方でGLMOpenGLとGLSLで簡単に噛み合うように設計され、それはインターフェースの非常に直感的なセットとC ++のための唯一の数学ライブラリ完全に機能するヘッダです。

ベクトルと行列の型、およびそれらに対するさまざまな操作を宣言します。

2つの行列を乗算するのは、(M1 * M2)のように簡単です。2つのベクトル(V1-V2)を減算します。

ベクトルまたは行列に含まれる値へのアクセスも同様に簡単です。たとえば、vec3ベクトルを宣言した後、vector.xを使用して最初の要素にアクセスできます。見てみな。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.