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

时间:2018-04-23 09:47:45

标签: c++ eigen eigen3

我正在使用一些遗留大量原始指针的遗留C代码。要与代码接口,我必须传递一个函数:

const int N = ...;

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

此函数应将结果写入x,然后返回x

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

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类将结果写回原始指针。

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

constraint = A - B;

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

  1. 构建Map对象
  2. 执行计算
  3. 将结果写入指针
  4. 因此,这条线可能具有最长的运行时间是可以理解的。但我有点担心,在将数据写入原始指针之前,我可能会以某种方式在该行中执行额外的复制。

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

    在我的脑海中,我想知道使用placement new语法是否会在这里给我带来任何东西。

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

1 个答案:

答案 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对象的构造本质上是一个无操作(它被任何编译器优化),不,这里没有额外的副本。

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