是否有C ++(或C)库具有类似NumPy的数组,并支持切片,向量化操作,逐元素添加和减去内容等?
是否有C ++(或C)库具有类似NumPy的数组,并支持切片,向量化操作,逐元素添加和减去内容等?
Answers:
这里有一些可能满足您需求的免费软件。
在GNU科学图书馆是用C编写因此,一个GPL软件,它具有类C(指针等)的分配和方式。使用GSLwrap,您可以使用C ++编程方式,同时仍使用GSL。GSL具有BLAS实现,但是如果您想获得更高的性能,则可以使用ATLAS代替默认的CBLAS。
的升压/ uBLAS库库是一个BSL库,用C ++编写和分布式作为升压包。这是实现BLAS标准的C ++方法。uBLAS具有一些线性代数函数,并且与ATLAS有实验绑定。
eigen是一个用C ++编写的线性代数库,以MPL2许可证(从3.1.1版开始)或LGPL3 / GPL2(旧版本)分发。这是一种C ++编程方式,但是比其他两种方式集成度更高(可用的算法和数据结构更多)。本征声称比上面的BLAS实现要快,但没有遵循事实上的标准BLAS API。Eigen似乎并没有在并行实现上投入很多精力。
Armadillo是C ++的LGPL3库。它具有对LAPACK(numpy使用的库)的绑定。它使用递归模板和模板元编程,这是一个好主意(我不知道其他库是否也在这样做吗?)。
xtensor是BSD许可的C ++库。它提供了一个与NumPy非常相似的C ++ API。有关备忘单,请参见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提供
例
初始化一个2-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被设计为C ++的类似NumPy的库。广播,算术运算符和切片之类的东西都可以正常工作。在另一方面,它仍然是非常实验和许多功能尚未实现。
这是使用DyND数组的C ++中的de Casteljau算法的简单实现:
#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,C ++中的DyND和Python中的NumPy的语法的更多示例和并排比较。
免责声明:我是目前的DyND开发人员之一。
本征是一个很好的线性代数库。
http://eigen.tuxfamily.org/index.php?title=Main_Page
由于它是仅标头的库,因此安装非常容易。它依靠模板来生成优化的代码。它自动矢量化矩阵运算。
它还完全支持系数明智的运算,例如,两个矩阵之间的“每元素乘法”。这是你需要的吗?
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]]
它没有提供将多个运算折叠在一起的复杂算术运算符,但是您可以将任意lambda广播到具有相同形状的一组张量,或者使用延迟评估的算术运算符。
让我知道您如何看待该接口,以及它与其他选项的比较,如果有希望,您希望实现哪种操作。
免费许可证,无依赖性!
附录:我设法正确编译并运行xtensor,结果是遍历视图时,我的库明显更快(2到3倍)
VIGRA包含良好的N维数组实现:
http://ukoethe.github.io/vigra/doc/vigra/Tutorial.html
我广泛使用它,发现它非常简单有效。它也只是标头,因此很容易集成到您的开发环境中。就API而言,这是我使用NumPy遇到的最接近的事情。
主要缺点是它没有像其他人那样广泛使用,因此您不会在网上找到太多帮助。那样,它的名称笨拙(尝试搜索!)
使用LibTorch(C ++的PyTorch前端)并感到高兴。
如果要使用多维数组(例如numpy)进行图像处理或神经网络,则可以OpenCV
cv::Mat
与大量图像处理算法一起使用。如果只想将其用于矩阵运算,则只需编译各自的opencv模块以减小大小,并使用微型OpenCV库。
cv::Mat
(Matrix)是一个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库,仅用于矩阵操作。一种方式就像本文中提到的那样。
要么
使用以下cmake命令编译opencv源代码:
$ 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]
虽然GLM旨在轻松地与OpenGL和GLSL啮合,但它是C ++的全功能标头数学库,具有非常直观的界面集。
它声明向量和矩阵类型以及它们的各种运算。
将两个矩阵相乘很简单(M1 * M2)。减去两个向量(V1-V2)。
访问向量或矩阵中包含的值同样简单。例如,在声明vec3向量后,可以使用vector.x访问其第一个元素。一探究竟。