Table Of Contents

Next topic

Quick Reference

This Page

Installation

Remora is hosted on Github under the LGPL-3 license.

Remora is header-only and depends only on header-only boost c++ libraries. Just download and copy the contents of the include/ folder into its target location. Currently the project can only be downloaded from github:

git clone https://github.com/Shark-ML/Remora

Summary

Remora is a general purpose linear algebra library written in C++11. It features:

  • dense and sparse matrix and vector operations
  • a basic set of optimized routines for matrix products, solving linear systems of equations, etc.
  • bindings to highly optimized routines of BLAS packages
  • a powerful expression template syntax which features algebraic optimizations of operations
  • Remora is header only, just plug and play!

The goal of Remora is to allow writing of formulas in C++ code as close to mathematical syntax as possible without penalties in runtime or numerical precision. Currently it relies on bindings for good performance.

Remora is designed for rapid prototyping, especially involving big matrices. It uses built-in rules deciding whether a set of operations can be exchanged by a set of more efficient operations. A simple example is a formula like \(B = A + A^T\). In general, this formula can be evaluated without a temporary by computing \(B_{ij} = A_{ij} + A_{ji}\). However, for big matrices this is very inefficient as we have to traverse the matrix along the rows and along the columns simultaneously, resulting in sub-optimal memory throughput. A more efficient order of computations is \(B=A\) followed by \(B+=A^T\). Remora does this simple transformation (and many more) automatically, allowing you to write concise equations which are as close to formulas as possible.

Quickstart

The power of Remora can be seen in the following lines. We use here linear regression as an example.

Remora gets included via:

#include <remora/remora.hpp>
using namespace remora;

We first generate the data and label matrices for linear regression:

std::size_t num_data_points = 100;
std::size_t num_dims = 50;
matrix<double> X(num_data_points, num_dims);
vector<double> y(num_data_points);

We skip the step of data generation, but X(i,j) = value; and y(i) = value; do the trick. The formula for linear regression with bias is \(w = ((X|1)^T(X|1))^{-1}(X|1)^T y\). Here, (X|1) stands for the matrix X where a column of ones is added to the end. In a typical implementation we have to be careful since the matrix may not have full rank, and use a pseudo-inverse instead:

vector<double> w = inv(trans(X|1) % (X|1), symm_semi_pos_def()) % trans(X|1) % y;

Operator % performs matrix-multiplication, trans(A) is matrix transposition, and inv(A,tag) performs matrix inversion where we have to supply information about how to invert that matrix. Note that no actual matrix inversion is taking place. The system automatically detects that the matrix inverse is multiplied with another matrix and instead instructs to solve a system of equations with multiple right hand sides \((X|1)^T\). Likewise it detects that the result is then multiplied with a vector from the right. This allows the transformation \(((X|1)^T(X|1)) w = (X|1)^Ty\) where we solve for \(w\).

Finally, we compute goodness of fit using the formula \(E(w)=\frac 1 {2N} \sum_{i=1}^N ((x_i|1)^Tw -y)^2\):

double error = 0.5 * sum(sqr((X|1) % w - y)) / num_data_points;

where sqr(x) is element-wise squaring of the entries and sum(x) sums all entries of the vector. We can check whether the solution found is actually correct by verifying that it is a minimizer, i.e., that is the derivative of the error measure above is close to 0:

vector<double> derE = trans(X|1) % ((X|1) % w - y) / num_data_points;
double error_derivative = norm_inf(derE);

norm_inf is the infinity norm, which returns the maximum element (in absolute value) of the vector.

Tutorials and Quick Reference

An overview of the operations supported by Remora is given in the Quick Reference

Compile Flags

When using Remora, the following defines can be supplied at compile time

  • REMORA_USE_SIMD if defined, Remora uses the compilers’ auto vectorizing capabilities to speed up its computational routines. Requires G++ or clang
  • REMORA_USE_CBLAS if defined, Remora binds to a cblas library. On MacOsX, this flag is interpreted as using the accelerate framework. Make sure to add the appropriate compile and linker flags for the library.
  • REMORA_USE_GPU if defined, Remora is enabling gpu support via the boost/compute library. Highly experimental.

Remora depends strogly on the optimization level of the compiler. In Debug, many costly index checks are performed to ensure correctness of the code, while in release high level of optimization should be applied.