如何将Eigen运算符内部解释为MKL函数?

时间:2018-06-12 02:52:00

标签: c++ memory eigen eigen3 intel-mkl

Eigen是一个非常方便的库,可以简洁,直观的方式表达数学公式。我知道Eigen具有惰性评估概念,可以表示表达式类中的一系列操作,并在必要时对其进行有效评估。我也知道Eigen可以和MKL一起使用。但是,我很好奇可以将哪种表达式转换为MKL cblas调用。在什么条件下,它们不可转让?是否有任何一般规则可以帮助我弄清楚什么是可转让的?

通常情况下,我对以下情况感到好奇:

MatrixXd A, B, C;
VectorXd a, b, c;
double w1, w2, w3;

b += w1 * A * a;  // can be done through dgemv
b += w1 * A.transpose() * a;  // can be done through dgemv
C += w2 * A * B;  // can be done through dgemm
C += w2 * A.transpose() * B;  // can be done through dgemm
C += w2 * A. topRows(5).transpose() * B;  // can be done through dgemm

D = A * B * C;    // cannot be done in one func call through cblas

注意:注释不是特征传递结果。相反,这是理想的结果。我不确定Eigen是否可以转移它们。

还有另一个问题:Eigen何时会在这些操作链中分配临时内存?是否有任何一般规则可以帮助我弄清楚是否有任何分配?

2 个答案:

答案 0 :(得分:2)

要完成chtz答案,您的所有假设都是正确的(假设您添加了.noalias()装饰器),更常见的是任何看起来像gemv / gemm的表达式或子表达式都将转为单个调用,包括转置您可以在此unit test中查找临时数量的示例,因此0表示单个类似blas的呼叫,1表示临时将是在blas-like call之前或之后创建等等。

答案 1 :(得分:1)

首先,为了避免示例中的临时性,您需要编写

b.noalias() += w1 * A * a;

这是因为Eigen无法在编译时告诉bAa没有别名,因此将产品评估为临时产品。 See here for details

Godbolt-demo:https://godbolt.org/g/VSfekp(请注意,-DEIGEN_USE_BLAS基本上等同于-DEIGEN_USE_MKL_ALL,但是Godbolt目前不支持MKL。

根据您的实际问题:要确定操作是否需要临时操作,您可以使用-DEIGEN_RUNTIME_NO_MALLOC编译并围绕您认为不应分配的部分

Eigen::set_is_malloc_allowed(false); // mallocs after this cause assertions
// some code
Eigen::set_is_malloc_allowed(true); // mallocs are allowed again

当然,这要求结果对象在输入该部分之前具有正确的大小。

此外,这对固定大小的表达式没有帮助,因为它们永远不会分配堆内存,但对于使用MKL的固定大小的表达式,通常效率低于Eigen(取决于大小,将完全展开必要的操作)。