C++ C++;特征库:Ref<;的性能开销&燃气轮机;
我正在使用计算力学的Egeng编写一个通用库, 主要处理6x6大小的矩阵和6x1大小的向量。 我考虑使用<代码> EGEN::REF模板,使其也适用于片段和块,如在文件和中所记载的那样。C++ C++;特征库:Ref<;的性能开销&燃气轮机;,c++,eigen,C++,Eigen,我正在使用计算力学的Egeng编写一个通用库, 主要处理6x6大小的矩阵和6x1大小的向量。 我考虑使用 EGEN::REF模板,使其也适用于片段和块,如在文件和中所记载的那样。 然而,一个小的性能比较表明, > EGEN::REF 相比于标准C++引用,这样的小函数具有相当大的开销: #include <ctime> #include <iostream> #include "Eigen/Core" Eigen::Matrix<double, 6, 6>
然而,一个小的性能比较表明,
#include <ctime>
#include <iostream>
#include "Eigen/Core"
Eigen::Matrix<double, 6, 6> testRef(const Eigen::Ref<const Eigen::Matrix<double, 6, 6>>& A)
{
Eigen::Matrix<double, 6, 6> temp = (A * A) * A;
temp.diagonal().setOnes();
return temp;
}
Eigen::Matrix<double, 6, 6> testNoRef(const Eigen::Matrix<double, 6, 6>& A)
{
Eigen::Matrix<double, 6, 6> temp = (A * A) * A;
temp.diagonal().setOnes();
return temp;
}
int main(){
using namespace std;
int cycles = 10000000;
Eigen::Matrix<double, 6, 6> testMat;
testMat = Eigen::Matrix<double, 6, 6>::Ones();
clock_t begin = clock();
for(int i = 0; i < cycles; i++)
testMat = testRef(testMat);
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
std::cout << "Ref: " << elapsed_secs << std::endl;
begin = clock();
for(int i = 0; i < cycles; i++)
testMat = testNoRef(testMat);
end = clock();
elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
std::cout << "noRef : " << elapsed_secs << std::endl;
return 0;
}
因此,Eigen::Ref
似乎有相当大的开销,至少在实际计算工作量较低的情况下是如此。
另一方面,如果传递了块或段,则使用常数特征::矩阵&A
的方法会导致不必要的拷贝:
#include <Eigen/Core>
#include <iostream>
void test( const Eigen::Vector3d& a)
{
std::cout << "addr in function " << &a << std::endl;
}
int main () {
Eigen::Vector3d aa;
aa << 1,2,3;
std::cout << "addr outside function " << &aa << std::endl;
test ( aa ) ;
test ( aa.head(3) ) ;
return 0;
}
因此,这种方法不适用于一般情况
或者,可以使用Eigen::MatrixBase
制作函数模板,如文档中所述。然而,对于大型库来说,这似乎是低效的,并且不能像我的例子那样适应固定大小的矩阵(6x6,6x1)
还有其他选择吗?
大型通用图书馆的一般建议是什么
提前谢谢你
编辑:根据注释中的建议修改第一个基准示例,使用Ref
您将付出失去两个信息的代价(与矩阵相比):
这是泛型和最高性能之间的经典折衷。无法在我得到的
Ref:0.069
noRef:0.069
上进行优化复制。如果没有优化的性能很重要,那么yeah Eigen通常会有巨大的开销,但这种情况在启用优化的情况下(例如,-O2
)会消失吗?如果不是,你的结果是不可信的,但如果。。。您的测试功能没有副作用。这就有一种危险,Eigen::Matrix temp=(A*A)代码>被优化掉了。您应该返回值,将其存储在向量中,然后打印(测量后),以防止由于优化而导致的“vanashing”。查看汇编也有助于发现您的代码实际到达二进制的部分。基准测试无效,因为一旦启用优化,编译器就可以自由地完全删除函数体。我修改了基准测试示例并启用了优化。然而,一个不同之处仍然存在。@macmallow我仍然不能可靠地使它变慢。VS2017现在让它慢了很多,但如果我继续重复测试,同一测试中的速度差异似乎高于两者之间的平均值差异。在gcc中,我现在发现Ref大部分时间都更快。我想是时候看看compilerversion、CPU和EigenVersion了。因此,我可以得出结论,我应该坚持尽可能长的C++引用(即,只要临时副本被排除),并实现功能与REF仅在必要时?
#include <Eigen/Core>
#include <iostream>
void test( const Eigen::Vector3d& a)
{
std::cout << "addr in function " << &a << std::endl;
}
int main () {
Eigen::Vector3d aa;
aa << 1,2,3;
std::cout << "addr outside function " << &aa << std::endl;
test ( aa ) ;
test ( aa.head(3) ) ;
return 0;
}
addr outside function 0x7fff85d75960
addr in function 0x7fff85d75960
addr in function 0x7fff85d75980