Mảng kiểu NumPy cho C ++?


83

Có bất kỳ lib C ++ (hoặc C) nào có mảng giống NumPy với hỗ trợ cho các phép toán cắt, vectơ hóa, thêm và trừ nội dung theo từng phần tử, v.v. không?



1
Theo như tôi biết thì numpy sử dụng LAPACK . Mặc dù điều đó được viết bằng Fortran, nhưng có sẵn các ràng buộc c ++. Không bao giờ sử dụng một trong hai mặc dù.
Voo

Có một giao diện C ++ gần đây cho NumPy, được gọi là ArmaNpy .
mtall

1
Tôi không thể nhìn thấy Boost.MultiArray trong các ý kiến được nêu ra
Dmitry Ledentsov

Bạn có thể thử nhúng Python và thực sự sử dụng numpy sẽ có lợi thế là không cần học thư viện mới, mặc dù nó sẽ chậm hơn so với sử dụng thư viện C / C ++.
Kevin

Câu trả lời:


57

Dưới đây là một số phần mềm miễn phí có thể phù hợp với nhu cầu của bạn.

  1. Các Thư viện khoa học GNU là một phần mềm GPL viết bằng C. Do đó, nó có một C-như phân bổ và cách lập trình (con trỏ, vv). Với GSLwrap , bạn có thể có cách lập trình C ++ trong khi vẫn sử dụng GSL. GSL có triển khai BLAS , nhưng bạn có thể sử dụng ATLAS thay vì CBLAS mặc định, nếu bạn muốn nhiều hiệu suất hơn nữa.

  2. Các tăng / uBLAS thư viện là một thư viện BSL, viết bằng C ++ và phân phối như là một gói tăng. Nó là một C ++ - cách thực hiện tiêu chuẩn BLAS. uBLAS đi kèm với một vài hàm đại số tuyến tính và có một ràng buộc thực nghiệm với ATLAS .

  3. eigen là một thư viện đại số tuyến tính được viết bằng C ++, được phân phối theo giấy phép MPL2 (bắt đầu từ phiên bản 3.1.1) hoặc LGPL3 / GPL2 (các phiên bản cũ hơn). Đó là một cách lập trình C ++, nhưng được tích hợp nhiều hơn hai cách khác (có sẵn nhiều thuật toán và cấu trúc dữ liệu hơn). Eigen tuyên bố là nhanh hơn các triển khai BLAS ở trên, trong khi không tuân theo API BLAS tiêu chuẩn de-facto. Eigen dường như không đặt nhiều nỗ lực vào việc thực hiện song song.

  4. Armadillo là thư viện LGPL3 cho C ++. Nó có ràng buộc cho LAPACK (thư viện được sử dụng bởi numpy). Nó sử dụng các mẫu đệ quy và lập trình siêu mẫu, đó là một điểm tốt (tôi không biết liệu các thư viện khác có làm điều đó không?).

  5. xtensor là một thư viện C ++ được cấp phép BSD. Nó cung cấp một API C ++ rất giống với API của NumPy. Xem https://xtensor.readthedocs.io/en/latest/numpy.html để biết bảng gian lận.

Những lựa chọn thay thế này thực sự tốt nếu bạn chỉ muốn lấy cấu trúc dữ liệu và đại số tuyến tính cơ bản. Tùy thuộc vào sở thích của bạn về kiểu dáng, giấy phép hoặc thách thức sysadmin (cài đặt các thư viện lớn như LAPACK có thể khó khăn), bạn có thể chọn cái phù hợp nhất với nhu cầu của mình.


15
Tin hay không thì tùy, câu trả lời của tôi là kết quả tìm kiếm của chính tôi, vài tháng trước. Tôi tin rằng việc thu thập những thông tin giúp tôi đưa ra lựa chọn sẽ có ích. Tôi không chắc là tốt hơn nên có một số thông tin trải rộng trên các câu trả lời. Bạn vẫn có thể ủng hộ mọi người nếu bạn cảm thấy lo lắng về đạo đức hơn là hiệu quả.
nojhan

19
Đáng buồn thay, không có cái nào trong số này cung cấp bất cứ thứ gì tổng quát và thuận tiện như mảng numpy. Mảng Numpy có kích thước tùy ý và hỗ trợ những thứ tương tự a[:4,::-1,:,19] = b[None,-5:,None]hoặc a[a>5]=0tương tự, cũng như có sẵn một bộ khổng lồ các hàm thao tác chỉ mục và mảng. Tôi thực sự hy vọng một ngày nào đó ai đó tạo ra một cái gì đó như vậy cho C ++.
amaurea

2
OpenCV cũng có kiểu Ma trận có thể có kích thước chiều tùy ý; phạm vi cột / hàng ( a.colRange(4,7).rowRange(4,8)cho a[4:7,4,8]) và mặt nạ điều kiện ( a.setTo(cv::Scalar(0), a>5)cho a[a>5]=0)
xaedes

3
@amaurea hãy xem câu trả lời trên xtensor bên dưới, câu trả lời cho phép tất cả những điều trên.
Quant

1
Tôi đã phải sử dụng Eigen trong một dự án gần đây và tôi phải nói rằng mặc dù nó có vẻ hiệu quả, nhưng cú pháp hoàn toàn khủng khiếp. Không có cú pháp cắt Python tuyệt vời nào có sẵn. Ví dụ, nếu bạn có một vector 1D x và muốn thao tác với n phần tử đầu tiên, bạn phải sử dụng x.head (n). Đừng hỏi về việc thao tác một lát x tùy ý, bạn sẽ cần một vòng lặp for cũ tốt để làm điều đó. Đây chỉ là một trong số rất nhiều ví dụ rắc rối và bất tiện mà tôi có thể nêu ra.
Alex,

53

Hãy thử xtensor . (Xem NumPy to Xtensor Cheat Sheet ).

xtensor là một thư viện C ++ dùng để phân tích số với các biểu thức mảng đa chiều.

xtensor cung cấp

  • một hệ thống biểu thức có thể mở rộng cho phép phát sóng kiểu numpy.
  • một API tuân theo các thành ngữ của thư viện chuẩn C ++.
  • các công cụ để thao tác biểu thức mảng và xây dựng dựa trên xtensor.

Thí dụ

Khởi tạo mảng 2-D và tính tổng của một trong các hàng của nó và mảng 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;

Kết quả đầu ra

{7, 11, 14}

Khởi tạo mảng 1-D và định hình lại nó ở vị trí.

#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;

Kết quả đầu ra

{{1, 2, 3},
 {4, 5, 6},
 {7, 8, 9}}

2
@Llamageddon bạn có nghĩ đây nên là câu trả lời được chọn không?
Quant

7

DyND được thiết kế để trở thành một thư viện giống NumPy cho C ++. Những thứ như phát sóng, toán tử số học và cắt đều hoạt động tốt. Mặt khác, nó vẫn rất thử nghiệm và nhiều tính năng vẫn chưa được triển khai.

Đây là cách triển khai đơn giản của thuật toán de Casteljau trong C ++ bằng cách sử dụng mảng 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;
}

Tôi đã viết một bài đăng trên blog cách đây ít lâu với nhiều ví dụ hơn và so sánh song song về cú pháp cho Fortran 90, DyND trong C ++ và NumPy trong Python.

Tuyên bố từ chối trách nhiệm: Tôi là một trong những nhà phát triển DyND hiện tại.


3

Eigen là một thư viện đại số tuyến tính tốt.

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

Nó khá dễ cài đặt vì nó là một thư viện chỉ dành cho tiêu đề. Nó dựa vào mẫu để tạo mã được tối ưu hóa tốt. Nó vectơ hóa tự động các hoạt động của ma trận.

Nó cũng hỗ trợ đầy đủ các phép toán khôn ngoan theo hệ số, chẳng hạn như "phép nhân mỗi phần tử" giữa hai ma trận. Nó là những gì bạn cần?


3
Cú pháp của Eigen khá khủng khiếp. Không có cú pháp nào trong số đó mà bạn tìm thấy trong Numpy. Và nó không phải là một thư viện mảng n-chiều tổng quát, nó chỉ dành cho vectơ 1D và ma trận 2D. Thực tế là họ có VectorXd cho mảng 1D và MatrixXd cho mảng 2D đã đẩy lùi tôi.
Alex,

2

Blitz ++ hỗ trợ mảng với số lượng trục tùy ý, trong khi Armadillo chỉ hỗ trợ tối đa ba (vectơ, ma trận và hình khối). Eigen chỉ hỗ trợ vectơ và ma trận (không phải hình khối). Nhược điểm là Blitz ++ không có các hàm đại số tuyến tính ngoài các phép toán cơ bản và các phép co tensor. Sự phát triển dường như đã chậm lại một thời gian trước đây, nhưng có lẽ đó chỉ là vì thư viện làm những gì nó làm và không có nhiều thay đổi cần được thực hiện.


2

xtensor là tốt, nhưng cuối cùng tôi đã tự viết một thư viện nhỏ như một dự án đồ chơi với c ++ 20, trong khi cố gắng giữ giao diện đơn giản nhất có thể. Đây rồi: https://github.com/gbalduzz/NDArray

Mã ví dụ:

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]]

Nó không cung cấp các toán tử số học ưa thích thu gọn nhiều phép toán lại với nhau, nhưng bạn có thể phát các lambdas tùy ý đến một tập hợp các tensor có cùng hình dạng hoặc sử dụng các toán tử số học được đánh giá một cách lười biếng.

Hãy cho tôi biết bạn nghĩ gì về giao diện và cách nó so sánh với các tùy chọn khác, và nếu điều này có bất kỳ hy vọng nào, bạn muốn thực hiện loại thao tác nào.

Giấy phép miễn phí và không phụ thuộc!

Phụ lục: Tôi đã quản lý để biên dịch và chạy xtensor đúng cách, và kết quả là thư viện của tôi nhanh hơn đáng kể khi lặp qua các chế độ xem (2 đến 3X)


1

VIGRA chứa một triển khai mảng N chiều tốt:

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

Tôi sử dụng rộng rãi, và thấy nó rất đơn giản và hiệu quả. Nó cũng chỉ có tiêu đề, vì vậy rất dễ dàng để tích hợp vào môi trường phát triển của bạn. Đó là điều gần nhất mà tôi đã gặp khi sử dụng NumPy về API của nó.

Nhược điểm chính là nó không được sử dụng rộng rãi như những cái khác, vì vậy bạn sẽ không tìm thấy nhiều trợ giúp trực tuyến. Điều đó và nó được đặt tên một cách khó hiểu (hãy thử tìm kiếm nó!)



1

Đây là một câu hỏi cũ. Vẫn cảm thấy muốn trả lời. Suy nghĩ có thể giúp ích cho nhiều người, Đặc biệt là mã hóa pydevs trong C ++.

Nếu bạn đã làm việc với python numpy, thì NumCpp là một lựa chọn tuyệt vời. Nó tối giản về cú pháp và có các hàm hoặc phương thức tương tự như py numpy.

Phần so sánh trong doc readme cũng rất hay.

NumCpp

nc::NdArray<int> arr = {{4, 2}, {9, 4}, {5, 6}};
arr.reshape(5, 3);
arr.astype<double>();

0

Eigen là một thư viện mẫu cho đại số tuyến tính (ma trận, vectơ…). Nó chỉ là tiêu đề và sử dụng miễn phí (LGPL).


0

Nếu bạn muốn sử dụng mảng đa chiều (như numpy) để xử lý hình ảnh hoặc mạng nơ-ron, bạn có thể sử dụng OpenCV cv::Mat cùng với rất nhiều thuật toán xử lý hình ảnh. Trong trường hợp bạn CHỈ muốn sử dụng nó cho các hoạt động ma trận, bạn chỉ cần biên dịch các mô-đun opencv tương ứng để giảm kích thước và có thư viện OpenCV nhỏ.

cv::Mat(Ma trận) là một mảng n chiều có thể được sử dụng để lưu trữ nhiều loại dữ liệu khác nhau, chẳng hạn như RGB, HSV hoặc hình ảnh thang độ xám, vectơ có giá trị thực hoặc phức, các ma trận khác, v.v.

A Mat chứa các thông tin sau: width, height, type, channels, data, flags, datastart, dataendvà như vậy.

Nó có một số phương pháp để thao tác với ma trận. Phần thưởng bạn cũng có thể tạo trên các lõi CUDA cv::cuda::GpuMat.

Hãy xem xét tôi muốn tạo một ma trận với 10 hàng, 20 cột, nhập 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

TẶNG KEM:

Biên dịch thư viện opencv nhỏ và nhỏ gọn chỉ cho các phép toán ma trận. Một khi các cách như được đề cập trong bài viết này.

HOẶC LÀ

biên dịch mã nguồn opencv bằng lệnh cmake sau:

$ 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

Hãy thử ví dụ này:

 #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;
 }

Biên dịch mã bằng lệnh sau:

$ g++ -std=c++11 opencv_mat.cc -o opencv_mat `pkg-config --libs opencv` `pkg-config --cflags opencv`

Chạy tệp thực thi:

$ ./opencv_mat

OpenCV Version 3.4.2
My Mat :
[0, 0, 0, 0;
 0, 0, 0, 0]

-1

Các GSL là rất tốt, nó làm tất cả những gì bạn đang yêu cầu và nhiều hơn nữa. Nó được cấp phép theo GPL.


-1

Trong khi GLM được thiết kế để kết hợp dễ dàng với OpenGL và GLSL, nó là một thư viện toán học chỉ tiêu đề đầy đủ chức năng cho C ++ với một bộ giao diện rất trực quan.

Nó khai báo các kiểu vector & ma trận cũng như các phép toán khác nhau trên chúng.

Nhân hai ma trận đơn giản là (M1 * M2). Trừ hai vectơ (V1- V2).

Việc truy cập các giá trị chứa trong vectơ hoặc ma trận cũng đơn giản như nhau. Sau khi khai báo một vec-tơ vec3 chẳng hạn, người ta có thể truy cập phần tử đầu tiên của nó với vec-tơ.x. Kiểm tra nó ra.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.