C ++ 용 NumPy 스타일 배열?


84

슬라이싱, 벡터화 작업, 요소 별 콘텐츠 추가 및 빼기 등을 지원하는 NumPy와 유사한 배열을 가진 C ++ (또는 C) 라이브러리가 있습니까?



1
내가 아는 한 numpy는 LAPACK을 사용합니다 . Fortran으로 작성되었지만 C ++ 바인딩을 사용할 수 있습니다. 그래도 그중 어느 것도 사용하지 않았습니다.
Voo

ArmaNpy 라는 NumPy에 대한 최신 C ++ 인터페이스가 있습니다.
mtall

1
내가 볼 수없는 Boost.MultiArray을 코멘트에 아직
드미트리 Ledentsov에게

C / C ++ 라이브러리를 사용하는 것보다 느리지 만 Python을 포함하고 실제로 numpy를 사용하면 새 라이브러리를 배울 필요가 없다는 이점이 있습니다.
케빈

답변:


58

다음은 귀하의 요구에 맞는 몇 가지 무료 소프트웨어입니다.

  1. GNU 과학 라이브러리 따라서 C. 작성된 GPL 소프트웨어, 그것은 C 같은 프로그래밍 (포인터 등)의 할당 및 방법이있다. 으로 GSLwrap 여전히 GSL을 사용하는 동안, 당신은, 프로그램의 C ++ 방법이 있습니다. GSL에는 BLAS 구현이 있지만 더 많은 성능을 원한다면 기본 CBLAS 대신 ATLAS 를 사용할 수 있습니다 .

  2. 부스트 / uBLAS의 라이브러리는 BSL 라이브러리, C ++로 작성 부스트 패키지로 배포됩니다. BLAS 표준을 구현하는 C ++ 방식입니다. uBLAS에는 몇 가지 선형 대수 함수가 제공 되며 ATLAS에 대한 실험적 바인딩이 있습니다.

  3. eigen 은 C ++로 작성된 선형 대수 라이브러리로 MPL2 라이선스 (버전 3.1.1부터 시작) 또는 LGPL3 / GPL2 (이전 버전)에 따라 배포됩니다. C ++ 프로그래밍 방식이지만 다른 두 가지 방식보다 더 통합되어 있습니다 (더 많은 알고리즘과 데이터 구조를 사용할 수 있음). Eigen 은 위의 BLAS 구현보다 빠르지 만 사실상의 표준 BLAS API를 따르지 않는다고 주장합니다 . Eigen은 병렬 구현에 많은 노력을 기울이지 않는 것 같습니다.

  4. Armadillo 는 C ++ 용 LGPL3 라이브러리입니다. LAPACK (numpy에서 사용하는 라이브러리)에 대한 바인딩이 있습니다 . 재귀 템플릿과 템플릿 메타 프로그래밍을 사용합니다. 이것은 좋은 점입니다 (다른 라이브러리에서도이 작업을 수행하는지 모르겠습니까?).

  5. xtensor 는 BSD 라이센스가있는 C ++ 라이브러리입니다. NumPy와 매우 유사한 C ++ API를 제공합니다. 치트 시트는 https://xtensor.readthedocs.io/en/latest/numpy.html 을 참조 하십시오 .

이러한 대안은 데이터 구조와 기본 선형 대수를 얻고 자 할 때 정말 좋습니다. 스타일, 라이선스 또는 시스템 관리자 문제에 대한 취향에 따라 (LAPACK과 같은 큰 라이브러리를 설치하는 것이 어려울 수 있음) 필요에 가장 적합한 것을 선택할 수 있습니다.


15
믿거 나 말거나, 내 대답은 몇 달 전 내 자신의 검색 결과입니다. 제가 선택하는 데 도움이되는 정보를 수집하는 것이 흥미로울 것이라고 믿었습니다. 답변에 여러 정보를 분산시키는 것이 더 좋은지 잘 모르겠습니다. 효율성보다 윤리에 더 관심이 있다면 여전히 모든 사람을 찬성 할 수 있습니다.
nojhan

19
슬프게도 이들 중 어느 것도 numpy 배열만큼 일반적이고 편리한 것을 제공하지 않습니다. Numpy 배열은 임의의 차원이며 유사 a[:4,::-1,:,19] = b[None,-5:,None]하거나 a[a>5]=0유사한 것을 지원할 뿐만 아니라 방대한 배열 및 인덱스 조작 기능을 사용할 수 있습니다. 언젠가는 누군가가 C ++를 위해 그렇게 만들길 정말 바랍니다.
amaurea

2
OpenCV에는 또한 임의의 차원 크기를 가질 수있는 Matrix 유형이 있습니다. 열 / 행 범위 ( a.colRange(4,7).rowRange(4,8)for a[4:7,4,8]) 및 조건 마스크 ( a.setTo(cv::Scalar(0), a>5)for a[a>5]=0)
xaedes

3
@amaurea는 위의 모든 것을 가능하게하는 아래 xtensor에 대한 답변을 확인하십시오.
Quant

1
최근 프로젝트에서 Eigen을 사용해야했고 효율적으로 보이지만 구문은 절대적으로 끔찍합니다. 사용 가능한 놀라운 Python 슬라이싱 구문은 없습니다. 예를 들어, 1D 벡터 x가 있고 처음 n 개의 요소를 조작하려면 x.head (n)을 사용해야합니다. x의 임의의 조각을 조작하는 것에 대해 묻지 마십시오. 그렇게하려면 좋은 오래된 for 루프가 필요합니다. 이것은 내가 말할 수있는 많은 투박하고 불편한 예 중 하나 일뿐입니다.
Alex

54

xtensor를 사용해보십시오 . ( NumPy to Xtensor 치트 시트 참조 ).

xtensor는 다차원 배열 표현식을 사용한 수치 분석을위한 C ++ 라이브러리입니다.

xtensor는 제공합니다

  • numpy 스타일의 방송을 가능하게하는 확장 가능한 표현 시스템.
  • C ++ 표준 라이브러리의 관용구를 따르는 API.
  • xtensor를 기반으로 배열 표현식을 조작하고 빌드하는 도구.

2 차원 배열을 초기화하고 행 중 하나와 1 차원 배열의 합을 계산합니다.

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

1 차원 배열을 초기화하고 제자리에서 모양을 변경합니다.

#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 이것이 선택된 대답이어야한다고 생각하십니까?
Quant

7

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 개발자 중 한 명입니다.


3

Eigen은 좋은 선형 대수 라이브러리입니다.

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

헤더 전용 라이브러리이기 때문에 설치가 매우 쉽습니다. 잘 최적화 된 코드를 생성하기 위해 템플릿에 의존합니다. 매트릭스 연산을 자동으로 벡터화합니다.

또한 예를 들어 두 행렬 간의 "요소 별 곱셈"과 같은 계수 현명한 연산을 완벽하게 지원합니다. 그것은 당신이 필요로하는 것입니까?


3
Eigen의 구문은 꽤 끔찍합니다. Numpy에서 찾을 수있는 부드러운 슬라이싱 구문은 없습니다. 그리고 이것은 일반적인 n 차원 배열 라이브러리가 아니라 1D 벡터와 2D 행렬만을위한 것입니다. 그들이 1D 배열을위한 VectorXd와 2D 배열을위한 MatrixXd를 가지고 있다는 사실은 이미 저를 반발합니다.
Alex는

2

Blitz ++ 는 임의 개수의 축이있는 배열을 지원하는 반면 Armadillo는 최대 3 개 (벡터, 행렬 및 큐브) 만 지원합니다. 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 배에서 3 배까지).


1

VIGRA에는 좋은 N 차원 배열 구현이 포함되어 있습니다.

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

광범위하게 사용하고 있으며 매우 간단하고 효과적입니다. 또한 헤더 전용이므로 개발 환경에 매우 쉽게 통합 할 수 있습니다. API 측면에서 NumPy를 사용하는 것과 가장 가까운 것입니다.

가장 큰 단점은 다른 것만 큼 널리 사용되지 않기 때문에 온라인에서 많은 도움을 찾을 수 없다는 것입니다. 이름이 어색합니다 (검색해보세요!).



1

이것은 오래된 질문입니다. 여전히 대답하고 싶었습니다. 생각은 많은 사람들에게 도움이 될 수 있습니다. 특히 C ++로 코딩하는 pydevs.

이미 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(Matrix)는 RGB, HSV 또는 회색조 이미지, 실수 또는 복소수 값이있는 벡터, 기타 행렬 등과 같은 다양한 유형의 데이터를 저장하는 데 사용할 수있는 n 차원 배열입니다.

매트에는 다음 정보가 포함 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]

-1

GSL은 당신이 묻는 훨씬 더하는지의 모든 작업을 수행, 중대하다. 그래도 GPL에 따라 라이센스가 부여됩니다.


-1

GLM 은 OpenGL 및 GLSL과 쉽게 맞물 리도록 설계 되었지만 , 매우 직관적 인 인터페이스 세트를 갖춘 C ++ 용 헤더 전용 수학 라이브러리입니다.

벡터 및 행렬 유형뿐만 아니라 다양한 연산을 선언합니다.

두 행렬을 곱하는 것은 (M1 * M2)처럼 간단합니다. 두 벡터 (V1- V2)를 뺍니다.

벡터 나 행렬에 포함 된 값에 액세스하는 것도 똑같이 간단합니다. 예를 들어 vec3 벡터를 선언 한 후 vector.x를 사용하여 첫 번째 요소에 액세스 할 수 있습니다. 확인 해봐.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.