Существуют ли какие-либо библиотеки C ++ (или C) с массивами, подобными NumPy, с поддержкой нарезки, векторизованных операций, добавления и вычитания содержимого по элементам и т. Д.?
Существуют ли какие-либо библиотеки C ++ (или C) с массивами, подобными NumPy, с поддержкой нарезки, векторизованных операций, добавления и вычитания содержимого по элементам и т. Д.?
Ответы:
Вот несколько бесплатных программ, которые могут удовлетворить ваши потребности.
GNU Scientific Library является GPL программное обеспечение , написанное на языке C. Таким образом, он имеет С-подобного распределения и способ программирования (указатели и т.д.). С GSLwrap вы можете программировать на C ++, продолжая использовать GSL. GSL имеет реализацию BLAS , но вы можете использовать ATLAS вместо CBLAS по умолчанию, если хотите еще больше производительности.
Библиотека boost / uBLAS - это библиотека BSL, написанная на C ++ и распространяемая как пакет boost. Это C ++ - способ реализации стандарта BLAS. uBLAS поставляется с несколькими функциями линейной алгебры, и есть экспериментальная привязка к ATLAS .
eigen - это библиотека линейной алгебры, написанная на C ++, распространяется по лицензии MPL2 (начиная с версии 3.1.1) или LGPL3 / GPL2 (более старые версии). Это способ программирования на C ++, но более интегрированный, чем два других (доступно больше алгоритмов и структур данных). Eigen утверждает, что работает быстрее, чем реализации BLAS, описанные выше, но при этом не соответствует стандарту де-факто BLAS API. Эйген, похоже, не прилагает много усилий для параллельной реализации.
Armadillo - это библиотека LGPL3 для C ++. Он имеет привязку к LAPACK (библиотека, используемая numpy). Он использует рекурсивные шаблоны и метапрограммирование шаблонов, что является хорошим моментом (я не знаю, делают ли это и другие библиотеки?).
xtensor - это библиотека C ++, имеющая лицензию BSD. Он предлагает API C ++, очень похожий на API 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 к Xtensor ).
xtensor - это библиотека C ++, предназначенная для численного анализа с многомерными выражениями массивов.
xtensor обеспечивает
пример
Инициализируйте двумерный массив и вычислите сумму одной из его строк и одномерного массива.
#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 doc тоже очень-очень классная.
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. Проверить это.