Eigen (C++ library): Difference between revisions

From David's Wiki
 
(10 intermediate revisions by the same user not shown)
Line 1: Line 1:
Eigen is a template header-only C++ linear algebra library. It is one of the fastest and most popular.
Eigen is a template header-only C++ linear algebra library. You can think of it as as [[numpy]] for C++.


[http://eigen.tuxfamily.org/index.php?title=Main_Page Website]
[http://eigen.tuxfamily.org/index.php?title=Main_Page Website]
Line 8: Line 8:
For optimal performance, I recommend using the following flags when compiling.<br>
For optimal performance, I recommend using the following flags when compiling.<br>
====GCC====
====GCC====
*<code>-mfma</code> Enable fused multiply add
*<code>-march=native</code> and <code>-mtune=native</code> if running only locally or <code>-march=skylake</code> if distributing to relatively modern (since ~2015) cpus.
*<code>-mavx2</code> Enable avx2 vector instructions
**Otherwise, at a minimum
**<code>-mfma</code> Enable fused multiply add
**<code>-mavx2</code> Enable avx2 vector instructions
*<code>-DEIGEN_NO_DEBUG</code> Set preprocessor define for eigen optimizations
*<code>-DEIGEN_NO_DEBUG</code> Set preprocessor define for eigen optimizations
*<code>-fopenmp</code> OpenMP parallel execution
*<code>-fopenmp</code> OpenMP parallel execution
*<code>-O3</code> to enable optimizations
===Data to Eigen===
You can use [https://eigen.tuxfamily.org/dox/classEigen_1_1Map.html <code>Eigen::Map</code>] to create an eigen view for your existing data.
This works with aligned or unaligned data, row-order or column-order, and different strides.<br>
See [https://eigen.tuxfamily.org/dox/group__TutorialMapClass.html Eigen: Interfacing with raw buffers] for an example.
==Math==
===SVD===
Eigen comes with a few SVD implementations in its [https://eigen.tuxfamily.org/dox/group__SVD__Module.html SVD Module].<br>
If you only need low-rank approximations then you may be interested in randomized SVD.<br>
This can be 10-20x faster when calculating low-rank approximations on large matrices.<br>
[https://github.com/kazuotani14/RandomizedSvd Github Implementation]<br>
[https://arxiv.org/abs/0909.4061 Finding structure with randomness paper]<br>
[https://research.fb.com/blog/2014/09/fast-randomized-svd/ Facebook Blog post]
==Unsupported==
===FFT===
https://eigen.tuxfamily.org/dox/unsupported/group__FFT__Module.html<br>
https://gitlab.com/libeigen/eigen/-/blob/master/unsupported/Eigen/FFT?ref_type=heads<br>
https://eigen.tuxfamily.org/index.php?title=EigenFFT<br>
This uses either kissfft (default), FFTW ('''GPL'''), Intel oneMKL, or pocketFFT under the hood.
There is very little documentation on this so it's easier to just read the code:
<syntaxhighlight lang="cpp">
// Initialize standard FFT.
Eigen::FFT<double> fft;
// Initialize RFFT
Eigen::FFT<double> fft(Eigen::FFT<double>::impl_type(), Eigen::FFT<double>::HalfSpectrum);
// Do the actual FFT or RFFT.
std::vector<double> my_data = {1.0, 2.0, 3.0, 4.0};
std::vector<std::complex<double>> fft_result;
fft.fwd(fft_result, my_data);
// Inverse
fft.inv(my_data, fft_result);
</syntaxhighlight>
'''Notes'''
* Alternative backend implementations can be set with <code>EIGEN_FFTW_DEFAULT</code>, <code>EIGEN_MKL_DEFAULT</code>, <code>EIGEN_POCKETFFT_DEFAULT</code>
* <code>fwd2</code> and <code>inv2</code> is available on the non-default backends.

Latest revision as of 20:38, 16 April 2024

Eigen is a template header-only C++ linear algebra library. You can think of it as as numpy for C++.

Website

Usage

Compilation

Reference
For optimal performance, I recommend using the following flags when compiling.

GCC

  • -march=native and -mtune=native if running only locally or -march=skylake if distributing to relatively modern (since ~2015) cpus.
    • Otherwise, at a minimum
    • -mfma Enable fused multiply add
    • -mavx2 Enable avx2 vector instructions
  • -DEIGEN_NO_DEBUG Set preprocessor define for eigen optimizations
  • -fopenmp OpenMP parallel execution
  • -O3 to enable optimizations

Data to Eigen

You can use Eigen::Map to create an eigen view for your existing data. This works with aligned or unaligned data, row-order or column-order, and different strides.
See Eigen: Interfacing with raw buffers for an example.

Math

SVD

Eigen comes with a few SVD implementations in its SVD Module.
If you only need low-rank approximations then you may be interested in randomized SVD.
This can be 10-20x faster when calculating low-rank approximations on large matrices.
Github Implementation
Finding structure with randomness paper
Facebook Blog post

Unsupported

FFT

https://eigen.tuxfamily.org/dox/unsupported/group__FFT__Module.html
https://gitlab.com/libeigen/eigen/-/blob/master/unsupported/Eigen/FFT?ref_type=heads
https://eigen.tuxfamily.org/index.php?title=EigenFFT


This uses either kissfft (default), FFTW (GPL), Intel oneMKL, or pocketFFT under the hood. There is very little documentation on this so it's easier to just read the code:

// Initialize standard FFT.
Eigen::FFT<double> fft;

// Initialize RFFT
Eigen::FFT<double> fft(Eigen::FFT<double>::impl_type(), Eigen::FFT<double>::HalfSpectrum);

// Do the actual FFT or RFFT.
std::vector<double> my_data = {1.0, 2.0, 3.0, 4.0};
std::vector<std::complex<double>> fft_result;
fft.fwd(fft_result, my_data);

// Inverse
fft.inv(my_data, fft_result);

Notes

  • Alternative backend implementations can be set with EIGEN_FFTW_DEFAULT, EIGEN_MKL_DEFAULT, EIGEN_POCKETFFT_DEFAULT
  • fwd2 and inv2 is available on the non-default backends.