Czy są jakieś biblioteki C ++ (lub C), które mają tablice podobne do NumPy z obsługą wycinania, operacji wektoryzacji, dodawania i odejmowania zawartości element po elemencie itp.?
Czy są jakieś biblioteki C ++ (lub C), które mają tablice podobne do NumPy z obsługą wycinania, operacji wektoryzacji, dodawania i odejmowania zawartości element po elemencie itp.?
Odpowiedzi:
Oto kilka bezpłatnych programów, które mogą odpowiadać Twoim potrzebom.
GNU Scientific Library to oprogramowanie GPL napisany w C. Tak więc, ma C-jak przydzielania i sposobu programowania (wskaźniki, etc.). Dzięki GSLwrap możesz programować w języku C ++, nadal używając GSL. GSL ma implementację BLAS , ale możesz użyć ATLAS zamiast domyślnego CBLAS, jeśli chcesz uzyskać jeszcze więcej wydajności.
Biblioteka boost / uBLAS jest biblioteką BSL napisaną w C ++ i rozpowszechnianą jako pakiet boost. Jest to sposób implementacji standardu BLAS w C ++. uBLAS zawiera kilka funkcji algebry liniowej oraz istnieje eksperymentalne powiązanie z ATLAS .
eigen to biblioteka algebry liniowej napisana w C ++, rozpowszechniana na licencji MPL2 (począwszy od wersji 3.1.1) lub LGPL3 / GPL2 (starsze wersje). Jest to sposób programowania w C ++, ale bardziej zintegrowany niż dwa pozostałe (dostępnych jest więcej algorytmów i struktur danych). Eigen twierdzi, że jest szybszy niż powyższe implementacje BLAS, ale nie jest zgodny z de facto standardowym BLAS API. Wydaje się, że Eigen nie wkłada wiele wysiłku w równoległe wdrażanie.
Armadillo to biblioteka LGPL3 dla C ++. Posiada powiązanie z LAPACK (biblioteka używana przez numpy). Używa szablonów rekurencyjnych i metaprogramowania szablonów, co jest dobrym punktem (nie wiem, czy inne biblioteki też to robią?).
xtensor to biblioteka C ++ na licencji BSD. Oferuje API C ++ bardzo podobne do NumPy. Zobacz https://xtensor.readthedocs.io/en/latest/numpy.html, aby uzyskać ściągawkę.
Te alternatywy są naprawdę dobre, jeśli chcesz tylko uzyskać struktury danych i podstawową algebrę liniową. W zależności od gustu w kwestii stylu, licencji lub wyzwań administratora systemu (instalacja dużych bibliotek, takich jak LAPACK może być trudna), możesz wybrać tę, która najlepiej odpowiada Twoim potrzebom.
a[:4,::-1,:,19] = b[None,-5:,None]
lub a[a>5]=0
i podobne, a także mają ogromny zestaw dostępnych funkcji manipulowania tablicami i indeksami. Naprawdę mam nadzieję, że ktoś kiedyś zrobi coś takiego dla C ++.
a.colRange(4,7).rowRange(4,8)
for a[4:7,4,8]
) i maska warunków ( a.setTo(cv::Scalar(0), a>5)
for a[a>5]=0
)
Wypróbuj xtensor . (Zobacz ściągawkę NumPy to Xtensor ).
xtensor to biblioteka C ++ przeznaczona do analizy numerycznej z wielowymiarowymi wyrażeniami tablicowymi.
xtensor zapewnia
Przykład
Zainicjuj tablicę 2-w i oblicz sumę jednego z jej wierszy i tablicy 1-w.
#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;
Wyjścia
{7, 11, 14}
Zainicjuj tablicę 1-W i zmień jej kształt w miejscu.
#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;
Wyjścia
{{1, 2, 3},
{4, 5, 6},
{7, 8, 9}}
DyND został zaprojektowany między innymi jako biblioteka podobna do NumPy dla C ++. Takie rzeczy jak nadawanie, operatory arytmetyczne i wycinanie działają dobrze. Z drugiej strony nadal jest bardzo eksperymentalny i wiele funkcji nie zostało jeszcze zaimplementowanych.
Oto prosta implementacja algorytmu de Casteljau w C ++ przy użyciu tablic DyND:
#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;
}
Niedawno napisałem post na blogu z większą ilością przykładów i porównaniami składni dla Fortran 90, DyND w C ++ i NumPy w Pythonie.
Zastrzeżenie: jestem jednym z obecnych programistów DyND.
Eigen to dobra biblioteka algebry liniowej.
http://eigen.tuxfamily.org/index.php?title=Main_Page
Jest dość łatwa do zainstalowania, ponieważ jest to biblioteka zawierająca tylko nagłówki. Opiera się na szablonie, aby wygenerować dobrze zoptymalizowany kod. Wektoryzuje automatycznie operacje macierzowe.
Obsługuje również w pełni operacje oparte na współczynnikach, takie jak na przykład mnożenie na element między dwiema macierzami. To jest to, czego potrzebujesz?
Blitz ++ obsługuje tablice z dowolną liczbą osi, podczas gdy Armadillo obsługuje tylko do trzech (wektory, macierze i kostki). Eigen obsługuje tylko wektory i macierze (nie kostki). Wadą jest to, że Blitz ++ nie ma funkcji algebry liniowej poza podstawowymi operacjami entrywise i skróceniami tensorowymi. Wydaje się, że rozwój zwolnił już jakiś czas temu, ale może to tylko dlatego, że biblioteka robi to, co robi i nie trzeba wprowadzać wielu zmian.
xtensor jest dobry, ale ostatecznie napisałem mini-bibliotekę jako projekt zabawki w języku c ++ 20, starając się jednocześnie maksymalnie uprościć interfejs. Oto on: https://github.com/gbalduzz/NDArray
Przykładowy kod:
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]]
Nie zapewnia jeszcze wymyślnych operatorów arytmetycznych, które zwijają wiele operacji razem, ale można rozgłaszać dowolne lambdy do zestawu tensorów o tym samym kształcie lub używać leniwie ocenianych operatorów arytmetycznych.
Daj mi znać, co myślisz o interfejsie i jak wypada on w porównaniu z innymi opcjami, a jeśli ma to jakąkolwiek nadzieję, jakie operacje chciałbyś zobaczyć zaimplementowane.
Darmowa licencja i brak zależności!
Dodatek: Udało mi się poprawnie skompilować i uruchomić xtensor, w wyniku czego moja biblioteka jest znacznie szybsza podczas iteracji po widokach (2 do 3X)
VIGRA zawiera dobrą implementację tablicy N-wymiarowej:
http://ukoethe.github.io/vigra/doc/vigra/Tutorial.html
Używam go intensywnie i uważam, że jest bardzo prosty i skuteczny. Jest to również tylko nagłówek, dzięki czemu jest bardzo łatwy do zintegrowania ze środowiskiem programistycznym. Jest to najbliższa rzecz, z jaką się spotkałem przy korzystaniu z NumPy, jeśli chodzi o jego API.
Głównym minusem jest to, że nie jest tak szeroko stosowany jak inne, więc nie znajdziesz zbyt wiele pomocy w Internecie. To i ma niezręczną nazwę (spróbuj go wyszukać!)
Użyj LibTorch (nakładka PyTorch dla C ++) i bądź szczęśliwy.
To jest stare pytanie. Nadal miałam ochotę odpowiedzieć. Myśl może pomóc wielu, zwłaszcza pidevs kodowanie w C ++.
Jeśli już pracowałeś z Pythonem numpy, NumCpp to świetny wybór. Jest minimalistyczny w składni i ma podobne funkcje lub metody jak py numpy.
Część porównawcza w dokumencie readme jest również bardzo fajna.
NumCpp
nc::NdArray<int> arr = {{4, 2}, {9, 4}, {5, 6}};
arr.reshape(5, 3);
arr.astype<double>();
Jeśli chcesz używać wielowymiarowej tablicy (takiej jak numpy) do przetwarzania obrazu lub sieci neuronowej, możesz użyć OpenCV
cv::Mat
wraz z mnóstwem algorytmów przetwarzania obrazu. Jeśli chcesz go używać TYLKO do operacji na macierzach, wystarczy skompilować odpowiednie moduły opencv, aby zmniejszyć rozmiar i mieć małą bibliotekę OpenCV.
cv::Mat
(Matryca) to n-wymiarowa tablica, która może być używana do przechowywania różnego rodzaju danych, takich jak obrazy RGB, HSV lub w skali szarości, wektory z wartościami rzeczywistymi lub złożonymi, inne macierze itp.
Mata zawiera następujące informacje: width, height, type, channels, data, flags, datastart, dataend
i tak dalej.
Posiada kilka metod manipulacji macierzą. Bonus, który możesz następnie stworzyć na rdzeniach CUDA, a także cv::cuda::GpuMat
.
Rozważ, że chcę utworzyć macierz z 10 wierszami, 20 kolumnami, wpisz 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
PREMIA:
Skompiluj małą i kompaktową bibliotekę opencv do wykonywania tylko operacji na macierzach. Jeden ze sposobów jest taki, jak wspomniano w tym artykule.
LUB
skompiluj kod źródłowy opencv za pomocą następującego polecenia 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
Wypróbuj ten przykład:
#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;
}
Skompiluj kod za pomocą następującego polecenia:
$ g++ -std=c++11 opencv_mat.cc -o opencv_mat `pkg-config --libs opencv` `pkg-config --cflags opencv`
Uruchom plik wykonywalny:
$ ./opencv_mat
OpenCV Version 3.4.2
My Mat :
[0, 0, 0, 0;
0, 0, 0, 0]
GSL jest super, robi wszystko, co prosisz i wiele więcej. Jest jednak licencjonowany na licencji GPL.
Chociaż GLM został zaprojektowany tak, aby łatwo łączyć się z OpenGL i GLSL, jest to w pełni funkcjonalna biblioteka matematyczna dla C ++ tylko z nagłówkiem z bardzo intuicyjnym zestawem interfejsów.
Deklaruje typy wektorowe i macierzowe, a także różne operacje na nich.
Mnożenie dwóch macierzy jest proste jak (M1 * M2). Odejmowanie dwóch wektorów (V1-V2).
Dostęp do wartości zawartych w wektorach lub macierzach jest równie prosty. Na przykład po zadeklarowaniu wektora vec3 można uzyskać dostęp do jego pierwszego elementu za pomocą vector.x. Sprawdź to.