- more performant parallel SVD algorithm:
eigenonly provides sequential SVD - alternative integration: currently only Gauss-Legendre quadrature is available
This is a C++ implementation of the VPMR algorithm to compute the approximation of arbitrary smooth kernel. A Python package is also provided.
Check the reference paper 10.1007/s10915-022-01999-1 and the original MATLAB implementation for more details.
In short, the algorithm tries to find a summation of exponentials to approximate a given kernel function.
In mathematical terms, it looks for a set of
In the above,
The following libraries are required:
- gmp for multiple precision arithmetic
- mpfr for multiple-precision floating-point computations
- tbb for parallel computing
The following libraries are included:
- mpreal
mprealtype C++ wrapper, included - Eigen for matrix decomposition, included
- exprtk for expression parsing, included
- exprtk-custom-types for
mprealsupport, included
If the application needs to be compiled on your machine (build the binary from source, python wheels are not available, etc.), you need to install the compiler and three libraries.
- On RPM-based Linux distributions (using
dnf), you need tosudo dnf install -y gcc-c++ tbb-devel mpfr-devel gmp-devel. - On DEB-based Linux distributions (using
apt), you need tosudo apt install -y g++ libtbb-dev libmpfr-dev libgmp-dev. - On macOS, you need to
brew install gcc tbb mpfr gmp.
If the binary is available (run the pre-compiled binary, python wheels are available, etc.), you only need the runtimes of three libraries.
You can find the exact names on pkgs.org by searching tbb, gmp and mpfr.
Warning
Windows users need to have a working MSYS2 environment. See below for more details.
For other environments, you need to figure out how to install gmp and mpfr on your own.
You can simply pull the image using the following command.
docker pull tlcfem/vpmr
# or using GitHub Container Registry
docker pull ghcr.io/tlcfem/vmprJust use it as you would normally do with any other docker images. For example,
docker run tlcfem/vpmr -n 30To build the image locally, use the provided Dockerfile.
wget -q https://raw.githubusercontent.com/TLCFEM/vpmr/master/resource/Dockerfile
docker build -t vpmr -f Dockerfile .Warning
The Python module needs external libraries to be installed. See above.
On most platforms (Linux and macOS), wheels are available, simply install the package with pip.
pip install pyvpmrIf the corresponding wheel is not available, the package will be compiled, which takes a few minutes.
The execution of the algorithm always requires available gmp, mpfr and tbb libraries.
import numpy as np
from pyvpmr import vpmr, plot
def kernel(x):
return np.exp(-x ** 2 / 4)
if __name__ == '__main__':
m, s = vpmr(n=50, k='exp(-t^2/4)')
plot(m, s, kernel)All available options are:
Usage: vpmr [options]
Options:
-n, --max-terms <int> number of terms (default: 10)
-c, --max-exponent <int> maximum exponent (default: 4)
-d, --precision-bits <int> number of precision bits (default: 512)
-q, --quadrature-order <int> quadrature order (default: 500)
-m, --precision-multiplier <float> precision multiplier (default: 1.05)
-e, --tolerance <float> tolerance (default: 1E-8)
-k, --kernel <string> file name of kernel function (default uses: exp(-t^2/4))
-s, --singular-values print singular values
-w, --weights print weights
-h, --help print this help message
The minimum required precision can be estimated by the parameter
The default kernel is exp(-t^2/4). One can run the application with the following command:
./vpmr -n 30The output is:
Using the following parameters:
terms = 30.
exponent = 4.
precision = 355.
quad. order = 500.
multiplier = 1.0500e+00.
tolerance = 1.0000e-08.
kernel = exp(-t*t/4).
[1/6] Computing weights... [60/60]
[2/6] Solving Lyapunov equation...
[3/6] Solving SVD...
[4/6] Transforming (P=+9)...
[5/6] Solving eigen decomposition...
[6/6] Done.
M =
+1.1745193571738943e+01+6.4196555242161141e-106j
-5.5143304351134397e+00+5.7204056791636839e+00j
-5.5143304351134397e+00-5.7204056791636839e+00j
-1.6161617424833762e-02+2.3459542440459513e+00j
-1.6161617424833762e-02-2.3459542440459513e+00j
+1.6338578576177487e-01+1.9308431539218418e-01j
+1.6338578576177487e-01-1.9308431539218418e-01j
-5.4905134221689715e-03+2.2104939243740062e-03j
-5.4905134221689715e-03-2.2104939243740062e-03j
S =
+1.8757961592204051e+00-0.0000000000000000e+00j
+1.8700580506914817e+00+6.2013413918954552e-01j
+1.8700580506914817e+00-6.2013413918954552e-01j
+1.8521958553280000e+00-1.2601975249082220e+00j
+1.8521958553280000e+00+1.2601975249082220e+00j
+1.8197653300065935e+00+1.9494562062795735e+00j
+1.8197653300065935e+00-1.9494562062795735e+00j
+1.7655956664692953e+00-2.7555720406099038e+00j
+1.7655956664692953e+00+2.7555720406099038e+00j
Running time: 2044 ms.
For arbitrary kernel, it is necessary to provide the kernel function in a text file.
The file should contain the kernel expressed as a function of variable t.
The exprtk is used to parse the expression and compute the value.
The provided kernel function must be valid and supported by exprtk.
Check the documentation regarding how to write a valid expression.
For example, to compute the approximation of exp(-t^2/10), one can create a file kernel.txt with the following
content:
exp(-t*t/10)
In the following, the kernel function is echoed to a file and then used as an input to the application.
echo "exp(-t*t/10)" > kernel.txt
./vpmr -n 60 -k kernel.txt -e 1e-12The majority of the algorithm is parallelised to extract the maximum performance.
The following is a typical performance profile on a i7-10750H platform using the ./vpmr -n 80.
Warning
The application relies on eigen and exprtk, which depend on very heavy usage of templates.
The compilation would take minutes and around 2 GB memory.
You need to install libraries gmp, mpfr and tbb before compiling.
Use the following instructions based on MSYS2, or follow the Linux instructions below with WSL.
# install necessary packages
pacman -S git mingw-w64-x86_64-cmake mingw-w64-x86_64-tbb mingw-w64-x86_64-gcc mingw-w64-x86_64-ninja mingw-w64-x86_64-gmp mingw-w64-x86_64-mpfr
# clone the repository
git clone --recurse-submodules --depth 1 https://github.com/TLCFEM/vpmr.git
cd vpmr
# apply patch to enable parallel evaluation of some loops in SVD
cd eigen && git apply --ignore-space-change --ignore-whitespace ../patch_size.patch && cd ..
# configure and compile
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release .
ninjaThe following is based on Fedora.
sudo dnf install gcc g++ cmake git tbb-devel mpfr-devel gmp-devel -y
git clone --recurse-submodules --depth 1 https://github.com/TLCFEM/vpmr.git
cd vpmr
cd eigen && git apply --ignore-space-change --ignore-whitespace ../patch_size.patch && cd ..
cmake -DCMAKE_BUILD_TYPE=Release .
make