Масиви стилів NumPy для C ++? [зачинено]


85

Чи існують бібліотеки C ++ (або C), які мають NumPy-подібні масиви з підтримкою нарізання, векторизованих операцій, додавання та віднімання вмісту поелементно тощо?



1
Наскільки я знаю, numpy використовує LAPACK . Незважаючи на те, що це написано на Fortran, доступні прив'язки c ++. Ніколи не використовував жодного з них.
Voo

Існує нещодавній інтерфейс C ++ для NumPy, який називається ArmaNpy .
mtall

1
Я ще не бачу Boost.MultiArray в коментарях
Дмитро Леденцов

Ви можете спробувати вбудувати Python і фактично скористатися numpy, який мав би ту перевагу, що не потрібно вивчати нову бібліотеку, хоча це було б повільніше, ніж використання бібліотеки C / C ++.
Кевін

Відповіді:


62

Ось кілька безкоштовних програм, які можуть відповідати вашим потребам.

  1. GNU Scientific Library є GPL програмне забезпечення , написане на мові C. Таким чином, він має С-подібного розподілу і спосіб програмування (покажчики і т.д.). За допомогою GSLwrap ви можете мати спосіб програмування на C ++, одночасно використовуючи GSL. GSL має реалізацію BLAS , але ви можете використовувати ATLAS замість CBLAS за замовчуванням, якщо хочете ще більше продуктивності.

  2. Бібліотека boost / uBLAS - це бібліотека BSL, написана на C ++ і розповсюджена як пакет підвищення. Це C ++ - спосіб впровадження стандарту BLAS. uBLAS поставляється з декількома лінійними функціями алгебри, і існує експериментальне зв’язування з ATLAS .

  3. eigen - це лінійна бібліотека алгебри, написана на C ++, що розповсюджується за ліцензією MPL2 (починаючи з версії 3.1.1) або LGPL3 / GPL2 (старіші версії). Це спосіб програмування на C ++, але більш інтегрований, ніж два інших (доступно більше алгоритмів та структур даних). Eigen стверджує, що він швидший, ніж реалізація BLAS вище, при цьому не дотримуючись фактичного стандартного API BLAS. Здається, Айген не докладає багато зусиль для паралельного впровадження.

  4. Armadillo - це бібліотека LGPL3 для C ++. Він має прив'язку до LAPACK (бібліотека, яку використовує numpy). Він використовує рекурсивні шаблони та метапрограмування шаблонів, що є хорошим моментом (я не знаю, чи роблять це інші бібліотеки?).

  5. xtensor - це бібліотека C ++, яка має ліцензію BSD. Він пропонує API C ++, дуже подібний до NumPy. Див. Https://xtensor.readthedocs.io/en/latest/numpy.html для шпаргалки.

Ці альтернативи дійсно хороші, якщо ви просто хочете отримати структури даних та базову лінійну алгебру. Залежно від вашого смаку щодо стилю, ліцензії або проблем із системою адміністрування (встановлення великих бібліотек, таких як LAPACK, може бути важким), ви можете вибрати ту, яка найкраще відповідає вашим потребам.


17
Вірте чи ні, але моя відповідь - це результат мого власного пошуку, який був місяць тому. Я вірив, що збір інформації, яка допомогла мені зробити вибір, буде цікавим. Я не впевнений, що краще, щоб кілька відповідей поширювались у відповідях. Ви все ще можете проголосувати за всіх, якщо вас більше турбує етика, аніж ефективність.
nojhan

19
На жаль, жоден з них не надає нічого такого загального та зручного, як масиви numpy. Масиви Numpy є довільновимірними і підтримують такі речі, як і a[:4,::-1,:,19] = b[None,-5:,None]чи a[a>5]=0подібні, а також мають величезний набір функцій обробки масивів та індексів. Я дуже сподіваюся, що хтось зробить щось подібне для C ++ одного дня.
amaurea 01.03.14

2
OpenCV також має тип матриці, який може мати довільний розмір; діапазони стовпців / рядків ( a.colRange(4,7).rowRange(4,8)для a[4:7,4,8]) та маска стану ( a.setTo(cv::Scalar(0), a>5)для a[a>5]=0)
xaedes

3
@amaurea ознайомтеся з відповіддю на xtensor нижче, що дає можливість усім вищесказаним.
Квант

1
Мені довелося використовувати Eigen в недавньому проекті, і я повинен сказати, що, хоча він здається ефективним, синтаксис абсолютно жахливий. Немає такого чудового синтаксису нарізки Python. Наприклад, якщо у вас є одновимірний вектор x і ви хочете маніпулювати першими n елементами, вам доведеться використовувати x.head (n). Навіть не питайте про маніпулювання довільним фрагментом x, для цього вам знадобиться старий добрий for-loop. Це лише один із багатьох незграбних та незручних прикладів, які я міг би назвати.
Олексій

54

Спробуйте xtensor . (Див. Шпаргалку NumPy to Xtensor ).

xtensor - це бібліотека на C ++, призначена для чисельного аналізу за допомогою багатовимірних виразів масивів.

xtensor надає

  • розширювана система виразів, що дозволяє транслювати в стилі Numpy.
  • API, що відповідає ідіомам стандартної бібліотеки 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}}

2
@Llamageddon, на вашу думку, це має бути обрана відповідь?
Квант

7

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.


3

Eigen - хороша бібліотека лінійної алгебри.

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

Встановити його досить просто, оскільки це бібліотека лише для заголовків. Він покладається на шаблон для створення добре оптимізованого коду. Він автоматично векторизує матричні операції.

Він також повністю підтримує коефіцієнтні операції, наприклад, "множення на елемент" між двома матрицями, наприклад. Це те, що вам потрібно?


3
Синтаксис Eigen досить жахливий. У Numpy немає такого синтаксису плавного нарізання. І це не загальна бібліотека n-вимірних масивів, вона більше стосується лише одновимірних векторів та 2D-матриць. Той факт, що вони мають VectorXd для одновимірних масивів і MatrixXd для 2D-масивів, мене вже відштовхує.
Олексій

2

Blitz ++ підтримує масиви з довільною кількістю осей, тоді як Armadillo підтримує лише три (вектори, матриці та куби). 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 до 3X)


1

VIGRA містить хорошу реалізацію N-вимірного масиву:

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

Я широко використовую його, і вважаю його дуже простим та ефективним. Це також лише заголовок, тому його дуже легко інтегрувати у своє середовище розробки. Це найближче, що я стикався з використанням NumPy з точки зору його API.

Основним недоліком є ​​те, що він не так широко використовується, як інші, тому ви не знайдете великої допомоги в Інтернеті. Це, і це незграбно названо (спробуйте шукати!)



1

Це давнє запитання. Все ще відчував, як відповісти. Думка може допомогти багатьом, особливо 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>();

0

Eigen - це бібліотека шаблонів для лінійної алгебри (матриці, вектори ...). Це лише заголовок і є безкоштовним у користуванні (LGPL).


0

Якщо ви хочете використовувати багатовимірний масив (наприклад, 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]

-1

GSL великий, він робить все , що ви просите , і багато іншого. Однак він ліцензований згідно з GPL.


-1

Хоча GLM розроблений для легкого з'єднання з OpenGL та GLSL, це повністю функціональна математична бібліотека заголовків для C ++ з дуже інтуїтивно зрозумілим набором інтерфейсів.

Він оголошує векторні та матричні типи, а також різні операції з ними.

Помноження двох матриць є простим як (M1 * M2). Віднімання двох векторів (V1- V2).

Доступ до значень, що містяться у векторах або матрицях, не менш простий. Наприклад, після оголошення вектора vec3 можна отримати доступ до його першого елемента за допомогою vector.x. Перевір.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.