C ++ için NumPy stili diziler? [kapalı]


85

NumPy benzeri dizilere sahip C ++ (veya C) kitaplıkları, dilimleme, vektörleştirilmiş işlemler, öğe öğe ekleme ve çıkarma vb. Desteği olan var mı?



1
Bildiğim kadarıyla numpy LAPACK kullanıyor . Bu Fortran'da yazılırken, c ++ bağlamaları mevcuttur. Bunlardan hiçbirini kullanmadım.
Voo

Denilen numpy için son C ++ arabirim vardır ArmaNpy .
mtall

1
Boost.MultiArray'i henüz yorumlarda göremiyorum
Dmitry Ledentsov

Python'u yerleştirmeyi deneyebilir ve gerçekten yeni bir kitaplık öğrenmeye ihtiyaç duymama avantajına sahip olan numpy kullanmayı deneyebilirsiniz, ancak bir C / C ++ kitaplığı kullanmaktan daha yavaş olacaktır.
Kevin

Yanıtlar:


62

İşte ihtiyaçlarınızı karşılayabilecek birkaç özgür yazılım.

  1. GNU Bilimsel Kütüphanesi Böylece C ile yazılmış bir GPL yazılımı, bir C-benzeri programlama (işaretçiler, vb) tahsisi ve yol vardır. İle GSLwrap hala GSL kullanırken, sen programlama C ++ yol olabilir. GSL'nin bir BLAS uygulaması vardır, ancak daha fazla performans istiyorsanız, varsayılan CBLAS yerine ATLAS kullanabilirsiniz .

  2. Boost / uBLAS kütüphanesi BSL kütüphanesi, C ++ yazılmış ve bir destek paket olarak dağıtılır. BLAS standardını uygulamanın bir C ++ yoludur. uBLAS, birkaç doğrusal cebir fonksiyonuyla birlikte gelir ve ATLAS'a deneysel bir bağlanma vardır .

  3. eigen , MPL2 lisansı (3.1.1 sürümünden başlayarak) veya LGPL3 / GPL2 (eski sürümler) altında dağıtılan, C ++ ile yazılmış doğrusal bir cebir kitaplığıdır. Bu bir C ++ programlama şeklidir, ancak diğer ikisinden daha entegre (daha fazla algoritma ve veri yapısı mevcuttur). Eigen , fiili standart BLAS API'yi takip etmemekle birlikte yukarıdaki BLAS uygulamalarından daha hızlı olduğunu iddia ediyor . Eigen, paralel uygulama için fazla çaba sarf etmiyor gibi görünüyor.

  4. Armadillo , C ++ için LGPL3 kitaplığıdır. LAPACK (numpy tarafından kullanılan kütüphane) için bağlayıcılığı vardır . Özyinelemeli şablonlar ve şablon meta programlama kullanır, bu iyi bir noktadır (diğer kütüphanelerin de bunu yapıp yapmadığını bilmiyorum?).

  5. xtensor , BSD lisanslı bir C ++ kitaplığıdır. NumPy'ye çok benzer bir C ++ API sunar. Hile sayfası için https://xtensor.readthedocs.io/en/latest/numpy.html adresine bakın .

Yalnızca veri yapılarını ve temel doğrusal cebiri elde etmek istiyorsanız, bu alternatifler gerçekten iyidir. Stil, lisans veya sysadmin zorlukları hakkındaki zevkinize bağlı olarak (LAPACK gibi büyük kitaplıklar kurmak zor olabilir), ihtiyaçlarınıza en uygun olanı seçebilirsiniz.


17
İster inanın ister inanmayın, cevabım bir ay önce kendi araştırmamın sonucudur. Seçimimi yapmama yardımcı olan bilgileri bir araya getirmenin biraz ilgi çekici olacağına inanıyordum. Cevaplara yayılmış birkaç bilginin daha iyi olup olmadığından emin değilim. Verimlilikten çok etikle ilgileniyorsanız yine de herkese olumlu oy verebilirsiniz.
nojhan

19
Ne yazık ki, bunların hiçbiri uyuşuk diziler kadar genel ve kullanışlı bir şey sağlamıyor. Numpy dizileri keyfi boyutludur ve benzeri a[:4,::-1,:,19] = b[None,-5:,None]veya a[a>5]=0benzeri şeyleri destekler , ayrıca çok sayıda dizi ve dizin işleme işlevine sahiptir. Umarım bir gün birileri C ++ için böyle bir şey yapar.
amaurea

2
OpenCV ayrıca rastgele boyutlara sahip olabilen bir Matrix türüne sahiptir; sütun / satır aralıkları ( a.colRange(4,7).rowRange(4,8)için a[4:7,4,8]) ve koşul maskesi ( a.setTo(cv::Scalar(0), a>5)için a[a>5]=0)
xaedes

3
@amaurea, yukarıdakilerin tümünü etkinleştiren aşağıdaki xtensor'daki yanıta bakın.
Quant

1
Yakın tarihli bir projede Eigen'i kullanmak zorunda kaldım ve verimli görünmesine rağmen, sözdiziminin kesinlikle korkunç olduğunu söylemeliyim. Bu şaşırtıcı Python dilimleme sözdiziminin hiçbiri mevcut değil. Örneğin, 1 boyutlu bir x vektörünüz varsa ve ilk n elemanı işlemek istiyorsanız, x.head (n) kullanmanız gerekir. Keyfi bir x dilimini manipüle etmeyi bile sormayın, bunu yapmak için eski bir for-döngüsüne ihtiyacınız olacak. Bu, sayabileceğim pek çok hantal ve rahatsız edici örnekten sadece biri.
Alex

54

Xtensor'u deneyin . ( NumPy'den Xtensor'a Hile Sayfasına bakın ).

xtensor, çok boyutlu dizi ifadeleri ile sayısal analiz için tasarlanmış bir C ++ kitaplığıdır.

xtensor sağlar

  • numpy tarzı yayın sağlayan genişletilebilir bir ifade sistemi.
  • C ++ standart kitaplığının deyimlerini izleyen bir API.
  • dizi ifadelerini işlemek ve xtensor üzerine inşa etmek için araçlar.

Misal

2 boyutlu bir diziyi başlatın ve satırlarından birinin ve 1 boyutlu dizinin toplamını hesaplayın.

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

çıktılar

{7, 11, 14}

Bir 1-D dizisini başlatın ve yerinde yeniden şekillendirin.

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

çıktılar

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

2
@Llamageddon bunun seçilen cevap olması gerektiğini düşünüyor musunuz?
Quant

7

DyND , diğer şeylerin yanı sıra C ++ için NumPy benzeri bir kitaplık olacak şekilde tasarlanmıştır. Yayın, aritmetik operatörler ve dilimleme gibi şeyler iyi çalışıyor. Öte yandan, hala çok deneysel ve birçok özellik henüz uygulanmadı.

DyND dizilerini kullanarak C ++ 'da de Casteljau algoritmasının basit bir uygulaması:

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

Kısa bir süre önce Fortran 90, C ++ 'da DyND ve Python'da NumPy için sözdiziminin daha fazla örneği ve yan yana karşılaştırmalarını içeren bir blog yazısı yazdım .

Sorumluluk reddi: Ben mevcut DyND geliştiricilerinden biriyim.


3

Eigen, iyi bir doğrusal cebir kütüphanesidir.

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

Yalnızca başlık içeren bir kitaplık olduğu için kurulumu oldukça kolaydır. İyi optimize edilmiş kod oluşturmak için şablona dayanır. Matris işlemlerini otomatik olarak vektörleştirir.

Aynı zamanda, örneğin iki matris arasındaki "eleman başına çarpma" gibi katsayı bilge işlemleri tam olarak destekler. İhtiyacın olan bu mu?


3
Eigen'in sözdizimi yine de oldukça korkunç. Numpy'de bulduğunuz pürüzsüz dilimleme sözdiziminin hiçbiri yoktur. Ve bu genel bir n boyutlu dizi kitaplığı değil, daha çok 1B vektörler ve 2B matrisler için. 1D diziler için VectorXd'ye ve 2D diziler için MatrixXd'ye sahip olmaları beni şimdiden itiyor.
Alex

2

Blitz ++ , keyfi sayıda eksen içeren dizileri desteklerken, Armadillo yalnızca üç adede kadar (vektörler, matrisler ve küpler) destekler. Eigen yalnızca vektörleri ve matrisleri destekler (küpleri değil). Dezavantajı, Blitz ++ 'nın temel girişsel işlemlerin ve tensör kasılmalarının ötesinde doğrusal cebir işlevlerine sahip olmamasıdır. Geliştirme epey bir zaman önce yavaşlamış gibi görünüyor, ama belki de bunun nedeni kütüphanenin yaptığını yapması ve çok fazla değişikliğin yapılmasına gerek olmamasıdır.


2

xtensor iyidir, ancak arayüzü olabildiğince basit tutmaya çalışırken c ++ 20 ile bir oyuncak projesi olarak kendime bir mini kitaplık yazdım. İşte burada: https://github.com/gbalduzz/NDArray

Örnek kod:

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

Birden çok işlemi birlikte daraltan fantezi aritmetik operatörler sağlamaz, ancak aynı şekle sahip bir tensöre rastgele lambdalar yayınlayabilir veya tembel olarak değerlendirilmiş aritmetik operatörleri kullanabilirsiniz.

Arayüz hakkında ne düşündüğünüzü ve diğer seçeneklerle nasıl karşılaştırıldığını ve bunun herhangi bir umudu varsa, ne tür operasyonların uygulanmasını istediğinizi bana bildirin.

Ücretsiz lisans ve bağımlılık yok!

Ek: xtensor'u düzgün bir şekilde derlemeyi ve çalıştırmayı başardım ve sonuç olarak, görünümler üzerinde yinelendiğinde kütüphanem önemli ölçüde daha hızlıdır (2 ila 3X)


1

VIGRA iyi bir N boyutlu dizi uygulaması içerir:

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

Yaygın olarak kullanıyorum ve çok basit ve etkili buluyorum. Ayrıca yalnızca başlıktır, geliştirme ortamınıza entegre etmek çok kolaydır. NumPy'yi API açısından kullandığım en yakın şey bu.

Başlıca dezavantajı, diğerleri kadar yaygın olarak kullanılmamasıdır, bu nedenle çevrimiçi olarak fazla yardım bulamazsınız. Bu ve garip bir şekilde adlandırıldı (aramayı deneyin!)



1

Bu eski bir sorudur. Hâlâ cevap veriyor gibiydi. Pek çok kişiye yardımcı olabileceğini düşündüm, özellikle de C ++ ile kodlayan pydevs.

Python numpy ile zaten çalıştıysanız, NumCpp harika bir seçimdir. Sözdiziminde minimalisttir ve py numpy ile benzer işlevlere veya yöntemlere sahiptir.

Karşılaştırma benioku doc part çok çok serin aynı zamanda.

NumCpp

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

0

Eigen , doğrusal cebir (matrisler, vektörler…) için bir şablon kitaplığıdır. Yalnızca başlıktır ve kullanımı ücretsizdir (LGPL).


0

Görüntü işleme veya sinir ağı için çok boyutlu dizi (numpy gibi) kullanmak istiyorsanız, OpenCV cv::Mattonlarca görüntü işleme algoritmasıyla birlikte kullanabilirsiniz . YALNIZCA matris işlemleri için kullanmak istemeniz durumunda, boyutu küçültmek ve küçük OpenCV kitaplığına sahip olmak için ilgili açıklık modüllerini derlemeniz yeterlidir.

cv::Mat(Matris), RGB, HSV veya gri tonlamalı görüntüler, gerçek veya karmaşık değerli vektörler, diğer matrisler vb. Gibi çeşitli veri türlerini depolamak için kullanılabilen n boyutlu bir dizidir.

Bir Paspas aşağıdaki bilgileri içerir: width, height, type, channels, data, flags, datastart, dataendvb.

Matris manipülasyonu için birkaç yöntemi vardır. Bonus daha sonra CUDA çekirdeklerinde de oluşturabilirsiniz cv::cuda::GpuMat.

10 satır, 20 sütunlu bir matris oluşturmak istediğimi düşünün, CV_32FC3 yazın:

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

BONUS:

Yalnızca matris işlemleri için küçük ve kompakt açıklıklı kitaplık derleyin. Yollardan biri bu makalede belirtildiği gibidir.

VEYA

aşağıdaki cmake komutunu kullanarak opencv kaynak kodunu derleyin:

$ 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

Bu örneği deneyin:

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

Kodu aşağıdaki komutla derleyin:

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

Yürütülebilir dosyayı çalıştırın:

$ ./opencv_mat

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

-1

GSL size soran ve çok daha fazlası şeyin hepsini yapıyor, harika. Yine de GPL altında lisanslanmıştır.


-1

İken GLM OpenGL ve GLSL ile kolayca örgü için tasarlanmıştır, bu arayüzler çok sezgisel bir set ile C için tamamen işlevsel başlık sadece matematik kütüphanesi ++ olduğunu.

Vektör ve matris türlerini ve bunlarla ilgili çeşitli işlemleri bildirir.

İki matrisi çarpmak (M1 * M2) kadar basittir. İki vektörün çıkarılması (V1-V2).

Vektörlerde veya matrislerde bulunan değerlere erişmek de aynı derecede basittir. Örneğin bir vec3 vektörü bildirdikten sonra, ilk elemanına vector.x ile erişilebilir. Bunu kontrol et.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.