用于C++的 NumPy 样式数组
NumPy style arrays for C++?
是否有任何C++(或 C)库具有类似 NumPy 的数组,支持切片、矢量化操作、逐个元素添加和减去内容等?
这里有几个可能适合您需求的免费软件。
-
GNU科学库是一个用C语言编写的GPL软件。因此,它具有类似 C 的分配和编程方式(指针等)。使用 GSLwrap,您可以在使用 GSL 的同时拥有C++编程方式。GSL有一个BLAS实现,但如果你想要更多的性能,你可以使用ATLAS而不是默认的CBLAS。
-
boost/uBLAS 库是一个 BSL 库,用 C++ 编写并作为 boost 包分发。这是实施BLAS标准的一种C++方法。uBLAS带有一些线性代数函数,并且与ATLAS有一个实验绑定。
-
eigen 是一个用 C++ 编写的线性代数库,在 MPL2 许可证(从版本 3.1.1 开始)或 LGPL3/GPL2(旧版本)下分发。这是一种C++编程方式,但比其他两种方式更集成(有更多的算法和数据结构可用)。Eigen声称比上面的BLAS实现更快,同时不遵循事实上的标准BLAS API。Eigen 似乎并没有在并行实现上投入太多精力。
-
犰狳是用于C++的LGPL3图书馆。它绑定了LAPACK(numpy使用的库)。它使用递归模板和模板元编程,这是一个很好的观点(我不知道其他库是否也在这样做?
-
xtensor 是一个 BSD 许可的C++库。它提供了一个与NumPy非常相似的C++ API。请参阅备忘单 https://xtensor.readthedocs.io/en/latest/numpy.html。
如果您只想获取数据结构和基本线性代数,这些替代方案非常好。根据您对样式、许可证或系统管理挑战的品味(安装像 LAPACK 这样的大型库可能很困难),您可以选择最适合您需求的库。
试试张量。(参见 NumPy 到 Xtensor 备忘单)。
Xtensor 是一个C++库,用于使用多维数组表达式进行数值分析。
张量提供
- 支持NUMPY样式广播的可扩展表达式系统。
- 遵循C++标准库习语的 API。
- 用于操作数组表达式和基于 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++库。广播、算术运算符和切片等功能都可以正常工作。另一方面,它仍然处于实验阶段,许多功能尚未实现。
以下是使用 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开发人员之一。
老问题。还是想回答。思想可能会帮助许多人,尤其是用C++编码的pydevs。
如果你已经使用过python numpy,那么NumCpp是一个不错的选择。它在语法上是简约的,并且具有与py numpy相似的功能或方法。
自述文件中的比较部分也非常非常酷。
NumCpp
nc::NdArray<int> arr = {{4, 2}, {9, 4}, {5, 6}};
arr.reshape(5, 3);
arr.astype<double>();
使用 LibTorch(C++ 的 PyTorch 前端)并感到高兴。
使用多维数组(如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 库,只用于矩阵操作。其中一种方法就像本文中提到的一样。
或
使用以下 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]
Eigen 是一个很好的线性代数库。
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 倍)
Blitz++ 支持具有任意轴数的数组,而犰狳最多只支持三个(矢量、矩阵和立方体)。 特征仅支持向量和矩阵(不支持立方体)。 缺点是 Blitz++ 除了基本的入口运算和张量收缩之外没有线性代数函数。 开发似乎在一段时间前就已经放缓了,但也许这只是因为库做了它所做的事情,不需要进行太多更改。
VIGRA 包含一个很好的 N 维数组实现:
http://ukoethe.github.io/vigra/doc/vigra/Tutorial.html
我广泛使用它,发现它非常简单有效。它也只是标头,因此很容易集成到您的开发环境中。就API而言,这是我遇到的最接近使用NumPy的东西。
主要缺点是它不像其他那样被广泛使用,因此您不会在网上找到太多帮助。那个,它的名字很尴尬(尝试搜索它!
虽然 GLM 旨在轻松与 OpenGL 和 GLSL 进行网格化,但它是一个功能齐全的仅标头数学库,用于具有一组非常直观的接口C++。
它声明了向量和矩阵类型以及对它们的各种操作。
将两个矩阵相乘是一个简单的 (M1 * M2)。减去两个向量 (V1- V2)。
访问向量或矩阵中包含的值同样简单。例如,在声明一个 vec3 向量之后,可以使用 vector.x 访问它的第一个元素。 看看吧。
Eigen 是一个线性代数(矩阵、向量等)的模板库。它仅是标头且免费使用 (LGPL)。
GSL 很棒,它可以满足您的所有要求以及更多。 不过,它是在GPL下授权的。
- 将包含C样式数组的对象初始化为成员变量(C++)
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当 std::move 与 C 样式数组或不移动对象时会发生什么
- 如何在谷歌模拟中匹配 C 样式数组
- 迭代器库中的 std::size() 不适用于传递给函数的 C 样式数组
- 解压缩 C 样式数组以及C++中的参数包
- 复制 C 样式数组和结构
- C++中循环和 C 样式数组的范围工作
- C++ - 移动具有固定大小的 c 样式数组成员的类的构造函数
- std::array与C样式数组用于连续内存
- 从原始指针(衰减的 C 样式数组)和大小生成范围::视图
- 不要声明 C 样式数组,而是使用 std::array<>
- 带C++的 C 样式数组?
- 如何从嵌套的 std::initializer_list 初始化 2D C 样式数组?
- 将 unique_ptr<std::vector> 与 c 样式数组结合使用
- 为什么我不能将 C 样式数组复制到 std::array?
- 函数需要 C 样式数组
- 键入 trait 以获取 std::array 或 C 样式数组的元素类型
- 何时需要删除 C 样式数组
- C++ C 样式数组作为语法错误的参数