NumPy-Arrays für C ++?

84

Gibt es C ++ (oder C) -Bibliotheken mit NumPy-ähnlichen Arrays, die das Schneiden, vektorisierte Operationen, das Hinzufügen und Subtrahieren von Inhalten Element für Element usw. unterstützen?

Llamageddon
quelle
2
Gürteltier ?
Oliver Charlesworth
1
Soweit ich weiß, benutzt numpy LAPACK . Während dies in Fortran geschrieben ist, sind C ++ - Bindungen verfügbar. Beides habe ich aber nie benutzt.
Voo
Es gibt eine aktuelle C ++ - Schnittstelle zu NumPy namens ArmaNpy .
Montag,
1
Ich kann Boost.MultiArray noch nicht in den Kommentaren sehen
Dmitry Ledentsov
Sie könnten versuchen, Python einzubetten und tatsächlich numpy zu verwenden, was den Vorteil hätte, dass Sie keine neue Bibliothek lernen müssen, obwohl dies langsamer wäre als die Verwendung einer C / C ++ - Bibliothek.
Kevin

Antworten:

58

Hier finden Sie einige kostenlose Software, die Ihren Anforderungen entsprechen kann.

  1. Die GNU Scientific Library ist eine in C geschriebene GPL-Software. Sie verfügt daher über eine C-ähnliche Zuordnung und Programmierweise (Zeiger usw.). Mit dem GSLwrap können Sie eine C ++ - Programmiermethode verwenden, während Sie weiterhin die GSL verwenden. GSL hat eine BLAS- Implementierung, aber Sie können ATLAS anstelle des Standard-CBLAS verwenden, wenn Sie noch mehr Leistung wünschen.

  2. Die Boost / uBLAS- Bibliothek ist eine BSL-Bibliothek, die in C ++ geschrieben und als Boost-Paket verteilt wird. Es ist eine C ++ - Methode zur Implementierung des BLAS-Standards. uBLAS enthält einige lineare Algebra-Funktionen und es gibt eine experimentelle Bindung an ATLAS .

  3. eigen ist eine in C ++ geschriebene lineare Algebra-Bibliothek, die unter der MPL2-Lizenz (ab Version 3.1.1) oder LGPL3 / GPL2 (ältere Versionen) vertrieben wird. Es ist eine C ++ - Programmiermethode, aber integrierter als die beiden anderen (es stehen mehr Algorithmen und Datenstrukturen zur Verfügung). Eigen behauptet, schneller als die oben genannten BLAS-Implementierungen zu sein, ohne der De-facto-Standard-BLAS-API zu folgen. Eigen scheint keine großen Anstrengungen für die parallele Implementierung zu unternehmen.

  4. Armadillo ist eine LGPL3-Bibliothek für C ++. Es ist für LAPACK (die von numpy verwendete Bibliothek) bindend. Es werden rekursive Vorlagen und Vorlagen-Metaprogrammierung verwendet, was ein guter Punkt ist (ich weiß nicht, ob andere Bibliotheken dies auch tun?).

  5. xtensor ist eine C ++ - Bibliothek mit BSD-Lizenz. Es bietet eine C ++ - API, die der von NumPy sehr ähnlich ist. Einen Spickzettel finden Sie unter https://xtensor.readthedocs.io/en/latest/numpy.html .

Diese Alternativen sind wirklich gut, wenn Sie nur Datenstrukturen und grundlegende lineare Algebra erhalten möchten. Abhängig von Ihrem Geschmack an Stil-, Lizenz- oder Systemadministrationsherausforderungen (die Installation großer Bibliotheken wie LAPACK kann schwierig sein) können Sie diejenige auswählen, die Ihren Anforderungen am besten entspricht.

Nojhan
quelle
15
Ob Sie es glauben oder nicht, meine Antwort ist das Ergebnis meiner eigenen Suche vor einigen Monaten. Ich glaubte, dass das Sammeln der Informationen, die mir bei meiner Wahl halfen, von Interesse sein würde. Ich bin mir nicht sicher, ob es besser ist, mehrere Informationen über die Antworten zu verteilen. Sie können immer noch alle positiv bewerten, wenn Sie sich mehr für Ethik als für Effizienz interessieren.
Nojhan
19
Leider bietet keines dieser Elemente etwas so Allgemeines und Bequemes wie numpy Arrays. Numpy Arrays sind beliebig dimensioniert und unterstützen ähnliche a[:4,::-1,:,19] = b[None,-5:,None]oder a[a>5]=0ähnliche Funktionen sowie eine Vielzahl von Funktionen zur Manipulation von Arrays und Indizes. Ich hoffe wirklich, dass irgendwann jemand so etwas für C ++ macht.
Amaurea
2
OpenCV hat auch einen Matrixtyp, der eine beliebige Dimensionsgröße haben kann. Spalten- / Zeilenbereiche ( a.colRange(4,7).rowRange(4,8)für a[4:7,4,8]) und Bedingungsmaske ( a.setTo(cv::Scalar(0), a>5)für a[a>5]=0)
xaedes
3
@amaurea Schauen Sie sich die Antwort auf xtensor unten an, die alle oben genannten Funktionen aktiviert.
Quant
1
Ich musste Eigen kürzlich in einem Projekt verwenden und ich muss sagen, dass die Syntax zwar schrecklich zu sein scheint, aber absolut schrecklich ist. Es gibt keine dieser erstaunlichen Python-Slicing-Syntax. Wenn Sie beispielsweise einen 1D-Vektor x haben und die ersten n Elemente bearbeiten möchten, müssen Sie x.head (n) verwenden. Fragen Sie nicht einmal nach der Manipulation eines beliebigen x-Slice, dafür benötigen Sie eine gute alte for-Schleife. Dies ist nur eines der vielen klobigen und unbequemen Beispiele, die ich nennen könnte.
Alex
54

Probieren Sie xtensor aus . (Siehe das NumPy to Xtensor Cheat Sheet ).

xtensor ist eine C ++ - Bibliothek zur numerischen Analyse mit mehrdimensionalen Array-Ausdrücken.

xtensor bietet

  • ein erweiterbares Ausdruckssystem, das Rundfunk im Numpy-Stil ermöglicht.
  • eine API, die den Redewendungen der C ++ - Standardbibliothek folgt.
  • Tools zum Bearbeiten von Array-Ausdrücken und zum Aufbau auf xtensor.

Beispiel

Initialisieren Sie ein 2D-Array und berechnen Sie die Summe einer seiner Zeilen und eines 1-D-Arrays.

#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;

Ausgänge

{7, 11, 14}

Initialisieren Sie ein 1-D-Array und formen Sie es neu.

#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;

Ausgänge

{{1, 2, 3},
 {4, 5, 6},
 {7, 8, 9}}
Quant
quelle
2
@ Lamageddon denkst du, das sollte die ausgewählte Antwort sein?
Quant
7

DyND soll unter anderem eine NumPy-ähnliche Bibliothek für C ++ sein. Dinge wie Rundfunk, Rechenoperatoren und Schneiden funktionieren einwandfrei. Andererseits ist es immer noch sehr experimentell und viele Funktionen wurden noch nicht implementiert.

Hier ist eine einfache Implementierung des de Casteljau-Algorithmus in C ++ unter Verwendung von DyND-Arrays:

#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;
}

Ich habe vor einiger Zeit einen Blog-Beitrag mit weiteren Beispielen und Vergleichen der Syntax für Fortran 90, DyND in C ++ und NumPy in Python geschrieben.

Haftungsausschluss: Ich bin einer der aktuellen DyND-Entwickler.

IanH
quelle
3

Eigen ist eine gute Bibliothek für lineare Algebra.

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

Die Installation ist recht einfach, da es sich um eine reine Header-Bibliothek handelt. Es basiert auf einer Vorlage, um gut optimierten Code zu generieren. Es vektorisiert automatisch die Matrixoperationen.

Es unterstützt auch vollständig koeffizientenweise Operationen, wie beispielsweise die "Multiplikation pro Element" zwischen zwei Matrizen. Es ist was du brauchst?

Frédéric Terrazzoni
quelle
3
Die Syntax von Eigen ist allerdings ziemlich schrecklich. Es gibt keine dieser Smooth-Slicing-Syntax, die Sie in Numpy finden. Und es ist keine allgemeine n-dimensionale Array-Bibliothek, sondern nur für 1D-Vektoren und 2D-Matrizen. Die Tatsache, dass sie VectorXd für 1D-Arrays und MatrixXd für 2D-Arrays haben, stößt mich bereits ab.
Alex
2

Blitz ++ unterstützt Arrays mit einer beliebigen Anzahl von Achsen, während Armadillo nur bis zu drei (Vektoren, Matrizen und Würfel) unterstützt. Eigen unterstützt nur Vektoren und Matrizen (keine Würfel). Der Nachteil ist, dass Blitz ++ keine linearen Algebra-Funktionen hat, die über die grundlegenden Eingangsoperationen und Tensorkontraktionen hinausgehen. Die Entwicklung scheint sich vor einiger Zeit verlangsamt zu haben, aber vielleicht liegt das nur daran, dass die Bibliothek das tut, was sie tut, und dass nicht viele Änderungen vorgenommen werden müssen.

Dan Stahlke
quelle
2

xtensor ist gut, aber am Ende habe ich selbst eine Mini-Bibliothek als Spielzeugprojekt mit c ++ 20 geschrieben und versucht, die Benutzeroberfläche so einfach wie möglich zu halten. Hier ist es: https://github.com/gbalduzz/NDArray

Beispielcode:

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]]

Es bietet noch keine ausgefallenen arithmetischen Operatoren, die mehrere Operationen zusammenfassen. Sie können jedoch beliebige Lambdas an eine Reihe von Tensoren mit derselben Form senden oder träge ausgewertete arithmetische Operatoren verwenden.

Lassen Sie mich wissen, was Sie über die Benutzeroberfläche denken und wie sie mit den anderen Optionen verglichen wird, und wenn dies Hoffnung hat, welche Art von Operationen möchten Sie implementiert sehen.

Kostenlose Lizenz und keine Abhängigkeit!

Nachtrag: Ich habe es geschafft, xtensor ordnungsgemäß zu kompilieren und auszuführen. Das Ergebnis ist, dass meine Bibliothek beim Durchlaufen von Ansichten (2 bis 3X) erheblich schneller ist.

Giovanni Balduzzi
quelle
1

VIGRA enthält eine gute N-dimensionale Array-Implementierung:

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

Ich benutze es ausgiebig und finde es sehr einfach und effektiv. Es ist auch nur Header, so sehr einfach in Ihre Entwicklungsumgebung zu integrieren. Es ist das, was mir bei der Verwendung von NumPy in Bezug auf die API am nächsten gekommen ist.

Der Hauptnachteil ist, dass es nicht so weit verbreitet ist wie die anderen, so dass Sie online nicht viel Hilfe finden. Das und es ist ungeschickt benannt (versuchen Sie es zu suchen!)

Martin
quelle
1

Verwenden Sie LibTorch (PyTorch-Frontend für C ++) und seien Sie glücklich.

Артем Ященко
quelle
1

Dies ist eine alte Frage. Ich hatte immer noch Lust zu antworten. Gedanken könnten vielen helfen, insbesondere Pydevs, die in C ++ codieren.

Wenn Sie bereits mit Python Numpy gearbeitet haben, ist NumCpp eine gute Wahl. Es ist minimalistisch in der Syntax und hat ähnliche Funktionen oder Methoden wie py numpy.

Der Vergleichsteil in der Readme-Datei ist auch sehr, sehr cool.

NumCpp

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

Eigen ist eine Vorlagenbibliothek für die lineare Algebra (Matrizen, Vektoren…). Es ist nur Header und kostenlos zu verwenden (LGPL).

Claudio
quelle
0

Wenn Sie ein mehrdimensionales Array (wie Numpy) für die Bildverarbeitung oder das neuronale Netzwerk verwenden möchten, können Sie es OpenCV cv::Matzusammen mit Tonnen von Bildverarbeitungsalgorithmen verwenden. Wenn Sie es NUR für Matrixoperationen verwenden möchten, müssen Sie nur die entsprechenden opencv-Module kompilieren, um die Größe zu verringern, und über eine winzige OpenCV-Bibliothek verfügen.

cv::Mat(Matrix) ist ein n-dimensionales Array, mit dem verschiedene Datentypen wie RGB-, HSV- oder Graustufenbilder, Vektoren mit reellen oder komplexen Werten, andere Matrizen usw. gespeichert werden können.

Eine Matte enthält die folgenden Informationen: width, height, type, channels, data, flags, datastart, dataendund so weiter.

Es gibt verschiedene Methoden zur Matrixmanipulation. Bonus können Sie dann auch auf CUDA-Kernen erstellen cv::cuda::GpuMat.

Angenommen, ich möchte eine Matrix mit 10 Zeilen und 20 Spalten vom Typ CV_32FC3 erstellen:

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

BONUS:

Kompilieren Sie eine winzige und kompakte OpenCV-Bibliothek für nur Matrixoperationen. Ein Weg ist wie in diesem Artikel erwähnt.

ODER

Kompilieren Sie den OpenCV-Quellcode mit dem folgenden Befehl cmake:

$ 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

Versuchen Sie dieses Beispiel:

 #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;
 }

Kompilieren Sie den Code mit folgendem Befehl:

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

Führen Sie die ausführbare Datei aus:

$ ./opencv_mat

OpenCV Version 3.4.2
My Mat :
[0, 0, 0, 0;
 0, 0, 0, 0]
Milind Deore
quelle
-1

Die GSL ist großartig, sie macht alles, was Sie verlangen und vieles mehr. Es ist jedoch unter der GPL lizenziert.

Matt Phillips
quelle
-1

Während GLM so konzipiert ist, dass es sich problemlos in OpenGL und GLSL einfügt, ist es eine voll funktionsfähige Mathe-Bibliothek nur für Header für C ++ mit einem sehr intuitiven Satz von Schnittstellen.

Es deklariert Vektor- und Matrixtypen sowie verschiedene Operationen auf ihnen.

Das Multiplizieren von zwei Matrizen ist einfach wie (M1 * M2). Subtrahieren von zwei Vektoren (V1 - V2).

Der Zugriff auf Werte, die in Vektoren oder Matrizen enthalten sind, ist ebenso einfach. Nachdem man beispielsweise einen vec3-Vektor deklariert hat, kann man mit vector.x auf sein erstes Element zugreifen. Hör zu.


quelle