Eigen:有效地将矩阵评估的输出存储在原始指针中

Eigen: Efficiently storing the output of a matrix evaluation in a raw pointer

我正在使用一些传递大量原始指针的遗留 C 代码。要与代码交互,我必须传递以下形式的函数:

const int N = ...;

T * func(T * x)  {
    // TODO Put N elements in x
    return x + N;
}

这个函数应该把结果写入x,然后return x.

在内部,在此函数中,我广泛使用 Eigen 来执行一些计算。然后我使用 Map class 将结果写回原始指针。一个模仿我正在做的事情的简单例子是:

const int N = 5;
T * func(T * x)  {

    // Do a lot of operations that result in some matrices like
    Eigen::Matrix<T, N, 1 > A = ... 
    Eigen::Matrix<T, N, 1 > B = ... 

    Eigen::Map<Eigen::Matrix<T, N, 1 >> constraint(x);
    constraint = A - B;

    return x + N;
}

显然,内部发生了更复杂的事情,但这就是它的要点......用 Eigen 做一些计算,然后用 Map class 写出结果回到原始指针。

现在的问题是,当我使用 Callgrind 分析此代码,然后使用 KCachegrind 查看结果时,行

constraint = A - B;

几乎总是瓶颈。这是可以理解的,因为这样的行 could/are 可能会做三件事:

  1. 构建地图对象
  2. 执行计算
  3. 将结果写入指针

所以这条线可能运行时间最长也是可以理解的。但我有点担心,在数据写入原始指针之前,我可能会以某种方式在该行中进行额外的复制。

那么有没有更好的方法将结果写入原始指针?或者这是我应该使用的成语?

在我的脑海深处,我想知道使用 placement new 语法是否能给我带来任何好处。

注意:这段代码是关键任务,应该 运行 实时,所以我真的需要从中榨取每一盎司的速度。例如,将此调用从 运行0.12 秒的时间缩短到 0.1 秒对我们来说意义重大。但代码的易读性也是一个巨大的问题,因为我们不断调整内部计算中使用的模型。

这两行代码:

Eigen::Map<Eigen::Matrix<T, N, 1 >> constraint(x);
constraint = A - B;

基本上由 Eigen 编译为:

for(int i=0; i<N; ++i)
  x[i] = A[i] - B[i];

由于显式展开和显式矢量化(两者都取决于 T),实际情况要复杂一些,但本质上就是这样。所以 Map 对象的构造本质上是一个空操作(它被任何编译器优化掉)而且不,这里没有额外的复制。

实际上,如果您的探查器能够告诉您瓶颈在于这个简单的表达式,那么这很可能意味着这段代码没有被内联,这意味着您没有启用编译器优化标志(比如-O3 与 gcc/clang).