我正在编写一个通用库,使用Eigen库进行计算力学,主要处理6x6大小的矩阵和6x1大小的向量。考虑使用
所以这种方法在一般情况下被排除了。相反,可以使用Eigen::MatrixBase来制作函数模板,如文档中所述。然而,对于大型库来说,这似乎效率低下,并且无法适应固定大小的矩阵(6x6、6x1),就像我遇到的情况一样。还有其他替代方法吗?对于大型通用库,有什么一般建议吗?提前感谢您!编辑:根据评论中的建议修改了第一个基准示例。
Eigen :: Ref <>
模板,使其也可用于段和块,如文档所述http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html和Correct usage of the Eigen::Ref<> class
然而,小型性能比较表明,与标准C ++引用相比,Eigen :: Ref
在这种小型函数中具有相当大的开销:#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;
}
使用 gcc -O3
输出:
Ref: 1.64066
noRef : 1.1281
看起来 Eigen::Ref
有相当大的开销,至少在实际计算工作量较低的情况下是如此。
另一方面,如果传递块或片段,则使用 const Eigen::Matrix<double, 6, 6>& 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;
}
输出:
addr outside function 0x7fff85d75960
addr in function 0x7fff85d75960
addr in function 0x7fff85d75980
所以这种方法在一般情况下被排除了。相反,可以使用Eigen::MatrixBase来制作函数模板,如文档中所述。然而,对于大型库来说,这似乎效率低下,并且无法适应固定大小的矩阵(6x6、6x1),就像我遇到的情况一样。还有其他替代方法吗?对于大型通用库,有什么一般建议吗?提前感谢您!编辑:根据评论中的建议修改了第一个基准示例。
Ref: 0.069
noRef: 0.069
。如果性能在没有优化的情况下很重要,那么Eigen通常会有巨大的开销,但这在大多数情况下都会消失。 - PeterT-O2
)?如果没有,你的结果是不可信的,但如果... 你的测试函数没有副作用。这带来了一个危险,即Eigen::Matrix<double, 6, 6> temp = (A * A);
可能会被优化掉。你应该返回值,将它们存储在一个vector
中,并在测量后打印它们,以防止它们因为优化而“消失”。查看汇编代码也可以帮助揭示你的代码实际上到达了二进制文件中的哪部分。 - Scheff's Cat