Чи існують бібліотеки C ++ (або C), які мають NumPy-подібні масиви з підтримкою нарізання, векторизованих операцій, додавання та віднімання вмісту поелементно тощо?
Чи існують бібліотеки C ++ (або C), які мають NumPy-подібні масиви з підтримкою нарізання, векторизованих операцій, додавання та віднімання вмісту поелементно тощо?
Відповіді:
Ось кілька безкоштовних програм, які можуть відповідати вашим потребам.
GNU Scientific Library є GPL програмне забезпечення , написане на мові C. Таким чином, він має С-подібного розподілу і спосіб програмування (покажчики і т.д.). За допомогою GSLwrap ви можете мати спосіб програмування на C ++, одночасно використовуючи GSL. GSL має реалізацію BLAS , але ви можете використовувати ATLAS замість CBLAS за замовчуванням, якщо хочете ще більше продуктивності.
Бібліотека boost / uBLAS - це бібліотека BSL, написана на C ++ і розповсюджена як пакет підвищення. Це C ++ - спосіб впровадження стандарту BLAS. uBLAS поставляється з декількома лінійними функціями алгебри, і існує експериментальне зв’язування з ATLAS .
eigen - це лінійна бібліотека алгебри, написана на C ++, що розповсюджується за ліцензією MPL2 (починаючи з версії 3.1.1) або LGPL3 / GPL2 (старіші версії). Це спосіб програмування на C ++, але більш інтегрований, ніж два інших (доступно більше алгоритмів та структур даних). Eigen стверджує, що він швидший, ніж реалізація BLAS вище, при цьому не дотримуючись фактичного стандартного API BLAS. Здається, Айген не докладає багато зусиль для паралельного впровадження.
Armadillo - це бібліотека LGPL3 для C ++. Він має прив'язку до LAPACK (бібліотека, яку використовує numpy). Він використовує рекурсивні шаблони та метапрограмування шаблонів, що є хорошим моментом (я не знаю, чи роблять це інші бібліотеки?).
xtensor - це бібліотека C ++, яка має ліцензію BSD. Він пропонує API C ++, дуже подібний до NumPy. Див. Https://xtensor.readthedocs.io/en/latest/numpy.html для шпаргалки.
Ці альтернативи дійсно хороші, якщо ви просто хочете отримати структури даних та базову лінійну алгебру. Залежно від вашого смаку щодо стилю, ліцензії або проблем із системою адміністрування (встановлення великих бібліотек, таких як LAPACK, може бути важким), ви можете вибрати ту, яка найкраще відповідає вашим потребам.
a[:4,::-1,:,19] = b[None,-5:,None]
чи a[a>5]=0
подібні, а також мають величезний набір функцій обробки масивів та індексів. Я дуже сподіваюся, що хтось зробить щось подібне для C ++ одного дня.
a.colRange(4,7).rowRange(4,8)
для a[4:7,4,8]
) та маска стану ( a.setTo(cv::Scalar(0), a>5)
для a[a>5]=0
)
Спробуйте xtensor . (Див. Шпаргалку NumPy to Xtensor ).
xtensor - це бібліотека на C ++, призначена для чисельного аналізу за допомогою багатовимірних виразів масивів.
xtensor надає
Приклад
Ініціалізуйте 2-D масив і обчисліть суму одного з його рядків та 1-D масиву.
#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}
Ініціалізуйте одновимірний масив і змініть його на місці.
#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}}
DyND створений, серед іншого, як NumPy-подібна бібліотека для C ++. Такі речі, як мовлення, арифметичні оператори та нарізка, працюють нормально. З іншого боку, це все ще дуже експериментально, і багато функцій ще не реалізовано.
Ось проста реалізація алгоритму де Кастеляу в C ++ з використанням масивів 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;
}
Нещодавно я написав допис у блозі з додатковими прикладами та паралельними порівняннями синтаксису для Fortran 90, DyND у C ++ та NumPy у Python.
Застереження: Я - один із сучасних розробників DyND.
Eigen - хороша бібліотека лінійної алгебри.
http://eigen.tuxfamily.org/index.php?title=Main_Page
Встановити його досить просто, оскільки це бібліотека лише для заголовків. Він покладається на шаблон для створення добре оптимізованого коду. Він автоматично векторизує матричні операції.
Він також повністю підтримує коефіцієнтні операції, наприклад, "множення на елемент" між двома матрицями, наприклад. Це те, що вам потрібно?
Blitz ++ підтримує масиви з довільною кількістю осей, тоді як Armadillo підтримує лише три (вектори, матриці та куби). Eigen підтримує лише вектори та матриці (не кубики). Недоліком є те, що Blitz ++ не має лінійних функцій алгебри, крім основних вхідних операцій та тензорних скорочень. Здається, розвиток сповільнився досить давно, але, можливо, це просто тому, що бібліотека робить те, що робить, і не потрібно вносити багато змін.
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 до 3X)
VIGRA містить хорошу реалізацію N-вимірного масиву:
http://ukoethe.github.io/vigra/doc/vigra/Tutorial.html
Я широко використовую його, і вважаю його дуже простим та ефективним. Це також лише заголовок, тому його дуже легко інтегрувати у своє середовище розробки. Це найближче, що я стикався з використанням NumPy з точки зору його API.
Основним недоліком є те, що він не так широко використовується, як інші, тому ви не знайдете великої допомоги в Інтернеті. Це, і це незграбно названо (спробуйте шукати!)
Використовуйте LibTorch (інтерфейс PyTorch для C ++) і будьте щасливі.
Це давнє запитання. Все ще відчував, як відповісти. Думка може допомогти багатьом, особливо pydevs, кодуючим на C ++.
Якщо ви вже працювали з python numpy, то NumCpp - чудовий вибір. Він мінімалістичний у синтаксисі і має подібні функції або методи, як py numpy.
Частина порівняння в документі readme також дуже класна.
NumCpp
nc::NdArray<int> arr = {{4, 2}, {9, 4}, {5, 6}};
arr.reshape(5, 3);
arr.astype<double>();
Якщо ви хочете використовувати багатовимірний масив (наприклад, numpy) для обробки зображень або нейронної мережі, ви можете використовувати OpenCV
cv::Mat
разом з безліччю алгоритмів обробки зображень. Якщо ви просто хочете використовувати його ТІЛЬКИ для матричних операцій, вам просто потрібно скомпілювати відповідні модулі opencv, щоб зменшити розмір, і мати крихітну бібліотеку OpenCV.
cv::Mat
(Матриця) - це n-вимірний масив, який може використовуватися для зберігання даних різного типу, таких як RGB, HSV або зображення в градаціях сірого, вектори з дійсними або складними значеннями, інші матриці тощо.
Килимок містить таку інформацію: 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 для просто матричних операцій. Один із способів подібний до того, як згадувалось у цій статті.
АБО
скомпілювати вихідний код opencv, використовуючи наступну команду 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
Спробуйте цей приклад:
#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]
GSL великий, він робить все , що ви просите , і багато іншого. Однак він ліцензований згідно з GPL.
Хоча GLM розроблений для легкого з'єднання з OpenGL та GLSL, це повністю функціональна математична бібліотека заголовків для C ++ з дуже інтуїтивно зрозумілим набором інтерфейсів.
Він оголошує векторні та матричні типи, а також різні операції з ними.
Помноження двох матриць є простим як (M1 * M2). Віднімання двох векторів (V1- V2).
Доступ до значень, що містяться у векторах або матрицях, не менш простий. Наприклад, після оголошення вектора vec3 можна отримати доступ до його першого елемента за допомогою vector.x. Перевір.