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?
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?
Antworten:
Hier finden Sie einige kostenlose Software, die Ihren Anforderungen entsprechen kann.
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.
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 .
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.
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?).
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.
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.
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
)
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
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}}
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.
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?
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.
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.
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!)
Verwenden Sie LibTorch (PyTorch-Frontend für C ++) und seien Sie glücklich.
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>();
Wenn Sie ein mehrdimensionales Array (wie Numpy) für die Bildverarbeitung oder das neuronale Netzwerk verwenden möchten, können Sie es OpenCV
cv::Mat
zusammen 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, dataend
und 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]
Die GSL ist großartig, sie macht alles, was Sie verlangen und vieles mehr. Es ist jedoch unter der GPL lizenziert.
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.