开发笔记:Eigen 开源库的应用

Eigen 与 C 之间数据转换

to Eigen

1
2
3
4
float* raw_data = malloc(...);
Map<MatrixXd> M(raw_data, rows, cols);
// use M as a MatrixXd
M = M.inverse();

from Eigen

1
2
3
4
MatrixXd M;
float* raw_data = M.data();
int stride = M.outerStride();
raw_data[i+j*stride]

一些预备知识

template programming

4 levels 并行

  • cluster of PCs --MPI
  • multi/many-cores -- OpenMP
  • SIMD -- intrinsics for vector instructions
  • pipelining -- needs non dependent instructions

Peak Performance

Example: Intel Core2 Quad CPU Q9400 @ 2.66GHz (x86_64)

* pipelining → 1 mul + 1 add / cycle (ideal case)
* SSE → x 4 single precision ops at once
* frequency → x 2.66G
* peak performance: 21,790 Mflops (for 1 core)

这就是我们优化的目标

Fused operation: Expression Template

Expression Template 是个好东西。通过编译融合嵌入的方式,减少了大量的读写和计算。

Curiously Recurring Template Pattern

Eigen 常见的坑

编译的时候最好 - DEIGEN_MPL2_ONLY (详见: Eigen)

这是因为 Eigen 虽然大部分是 MPL2 licensed 的,但是还有少部分代码是 LGPL licensed 的,如果修改了其代码,则必须开源。 这可能产生法律风险,而遭到法务部门的 Complain

要注意 alignment 的问题

1
2
3
4
5
6
7
my_program: path/to/eigen/Eigen/src/Core/DenseStorage.h:44:
Eigen::internal::matrix_array<T, Size, MatrixOptions, Align>::internal::matrix_array()
[with T = double, int Size = 2, int MatrixOptions = 2, bool Align = true]:
Assertion `(reinterpret_cast<size_t>(array) & (sizemask)) == 0 && "this assertion
is explained here: http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html
READ THIS WEB PAGE !!! ****"' failed.
There are 4 known causes for this issue. Please read on to understand them and learn how to fix them.

例如下面的代码都是有问题的,可能导致整个程序 Crash。

  • 结构体含有 Eigen 类型的成员变量
1
2
3
4
5
6
7
class Foo {
//...
Eigen::Vector2d v; // 这个类型只是一个例子,很多类型都有问题
//...
};
//...
Foo *foo = new Foo;
  • Eigen 类型的变量被放到 STL 容器中
1
2
3
4
// Eigen::Matrix2f这个类型只是一个例子,很多类型都有问题
std::vector<Eigen::Matrix2f> my_vector;
struct my_class { ... Eigen::Matrix2f m; ... };
std::map<int, my_class> my_map;
  • Eigen 类型的变量被按值传入一个函数
1
2
// Eigen::Vector4d只是一个例子,很多类型都有这个问题
void func(Eigen::Vector4d v);
  • 在栈上定义 Eigen 类型的变量 (只有 GCC4.4 及以下版本 on Windows 被发现有这个问题,例如 MinGW or TDM-GCC)
1
2
3
void foo() {
Eigen::Quaternionf q; // Eigen::Quaternionf只是一个例子,很多类型都有这个问题
}