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 可能会做三件事:
- 构建地图对象
- 执行计算
- 将结果写入指针
所以这条线可能运行时间最长也是可以理解的。但我有点担心,在数据写入原始指针之前,我可能会以某种方式在该行中进行额外的复制。
那么有没有更好的方法将结果写入原始指针?或者这是我应该使用的成语?
在我的脑海深处,我想知道使用 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).
我正在使用一些传递大量原始指针的遗留 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 可能会做三件事:
- 构建地图对象
- 执行计算
- 将结果写入指针
所以这条线可能运行时间最长也是可以理解的。但我有点担心,在数据写入原始指针之前,我可能会以某种方式在该行中进行额外的复制。
那么有没有更好的方法将结果写入原始指针?或者这是我应该使用的成语?
在我的脑海深处,我想知道使用 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).