fml blog   About

Introducing fml - the Fused Matrix Library

Written Sun, June 21, 2020.

What is fml?

fml is the Fused Matrix Library, a permissively licensed, header-only C++ library for dense matrix computing. The emphasis is on real-valued matrix types (float, double, and __half) for numerical operations useful for data analysis.

The library provides 3 main classes: cpumat, gpumat, and mpimat. There is currently an experimental parmat class, but it is at present not well developed. For the main classes:

There are some differences in how objects of any particular type are constructed. But the high level APIs are largely the same between the objects. The goal is to be able to quickly create laptop-scale prototypes that are then easily converted into large scale gpu/multi-node/multi-gpu/multi-node+multi-gpu codes.

Example

Here’s a quick example computing the singular values of a simple CPU matrix:

#include <fml/cpu.hh>

int main()
{
  fml::cpumat<float> x(3, 2);
  x.fill_linspace(1, 6);
  
  x.info();
  x.print(0);
  
  fml::cpuvec<float> s;
  fml::linalg::svd(x, s);
  
  s.info();
  s.print();
  
  return 0;
}

If we save this in svd.cpp, we can compile it with something like:

g++ -I/path/to/fml/src -fopenmp svd.cpp -o svd -llapack -lblas

And then running it, we see:

# cpumat 3x2 type=f
1 4 
2 5 
3 6 

# cpuvec 2 type=f
9.5080 0.7729 

With only minor modifications, we can do this same operation on a GPU:

#include <fml/gpu.hh>

int main()
{
  auto c = fml::new_card(0);
  c.info();
  
  fml::gpumat<float> x(c, 3, 2);
  x.fill_linspace(1, 6);
  
  x.info();
  x.print(0);
  
  fml::gpuvec<float> s(c);
  fml::linalg::svd(x, s);
  
  s.info();
  s.print();
  
  return 0;
}

If we save this in svd.cu, we can compile it with something like:

nvcc -arch=sm_61 -Xcompiler "-I/path/to/fml/src" svd.cu -o svd -lcudart -lcublas -lcusolver -lcurand -lnvidia-ml

And then running it, we see:

## GPU 0 (GeForce GTX 1070 Ti) 860/8116 MB - CUDA 10.2

# gpumat 3x2 type=f 
1 4 
2 5 
3 6 

# gpuvec 2 type=f 
9.5080 0.7729 

The Interface

I think that one person’s high-level is another person’s low-level. With that in mind, the goal of fml is to be “medium-level”. It’s high-level compared to working directly with e.g. the BLAS or cuBLAS, but low(er)-level compared to most other C++ matrix frameworks and things like R and Matlab.

If you want to learn more about the interface, you can read the doxygen documentation. There are also some basic examples.

I also maintain R bindings in the fmlr package. That may be a good place to start. I sort of think of it like an interactive REPL for fml with some minor modifications (e.g., replace x.method() with x$method()). The package is well-documented, and contains some long-form articles. I will have much more to say about fmlr in a later post.

Philosophy and Similar Projects

There are many high quality C/C++ matrix libraries. Of course Armadillo and Eigen are worth mentioning. Boost also has matrix bindings. GSL is a C library with numerous matrix operations. There is also PETSc, which can do some distributed operations, although it is mostly focused on sparse matrices.

With the exception of GSL, all of these are permissively licensed. Some have at least some level of GPU support, for example Armadillo and Eigen (perhaps others).

But I believe it is fair to say that none of these projects satisfies all of

That’s essentially the goal of fml. I believe this offers something legitimately new in what is already a crowded space of high-quality libraries.

State of the Project

The project is still pretty young, and at present only maintained/contributed to by one person, and only in my spare time. That said, it is currently usable and has quite a lot to offer if you operate at the level of linear algebra.

What’s there now:

What’s coming soon:

What I would like to have some day:


← SVD via Lanczos Iteration  Vignette-less Articles With pkgdown →


© 2020-2021. Post content is CC-BY-SA. Source code listings are CC0.