我使用Eigen進行類似於Cholesky更新的操作,這意味着在固定大小矩陣(通常是Matrix4d)的列上存在大量AXPY(總和加上標量乘)。簡而言之,它是3倍更昂貴的訪問的矩陣4的列比到Vector 4.Eigen:對矩陣的列訪問速度很慢4
典型地,下面的代碼:
for(int i=0;i<4;++i) L.col(0) += x*y[i];
比下面的代碼少3倍高效:
for(int i=0;i<4;++i) l4 += x*y[i];
,其中L是典型的大小爲4,X,Y的一個矩陣和L4 4.
此外大小的矢量,在第一行代碼所花費的時間不依賴於米atrix存儲組織(ColMajor的RowMajor)。
在Intel i7(2.5GHz)上,向量操作大約需要0.007us,矩陣操作需要0.02us(通過重複100000次同樣的操作完成定時)。我的應用程序需要數千次這樣的操作,希望遠低於毫秒。
問題:在訪問我的4x4矩陣的列時,我做了一些不正確的事情?有什麼需要做的,使第一行代碼更有效率?用於定時
完整代碼如下:
#include <iostream>
#include <Eigen/Core>
#include <vector>
#include <sys/time.h>
typedef Eigen::Matrix<double,4,1,Eigen::ColMajor> Vector4;
//typedef Eigen::Matrix<double,4,4,Eigen::RowMajor,4,4> Matrix4;
typedef Eigen::Matrix<double,4,4,Eigen::ColMajor,4,4> Matrix4;
inline double operator- ( const struct timeval & t1,const struct timeval & t0)
{
/* TODO: double check the double conversion from long (on 64x). */
return double(t1.tv_sec - t0.tv_sec)+1e-6*double(t1.tv_usec - t0.tv_usec);
}
void sumCols(Matrix4 & L,
Vector4 & x4,
Vector4 & y)
{
for(int i=0;i<4;++i)
{
L.col(0) += x4*y[i];
}
}
void sumVec(Vector4 & L,
Vector4 & x4,
Vector4 & y)
{
for(int i=0;i<4;++i)
{
//L.tail(4-i) += x4.tail(4-i)*y[i];
L += x4 *y[i];
}
}
int main()
{
using namespace Eigen;
const int NBT = 1000000;
struct timeval t0,t1;
std::vector< Vector4> x4s(NBT);
std::vector< Vector4> y4s(NBT);
std::vector< Vector4> z4s(NBT);
std::vector< Matrix4> L4s(NBT);
for(int i=0;i<NBT;++i)
{
x4s[i] = Vector4::Random();
y4s[i] = Vector4::Random();
L4s[i] = Matrix4::Random();
}
int sample = int(z4s[55][2]/10*NBT);
std::cout << "*** SAMPLE = " << sample << std::endl;
gettimeofday(&t0,NULL);
for(int i=0;i<NBT;++i)
{
sumCols(L4s[i], x4s[i], y4s[i]);
}
gettimeofday(&t1,NULL);
std::cout << (t1-t0) << std::endl;
std::cout << "\t\t\t\t\t\t\tForce check" << L4s[sample](1,0) << std::endl;
gettimeofday(&t0,NULL);
for(int i=0;i<NBT;++i)
{
sumVec(z4s[i], x4s[i], y4s[i]);
}
gettimeofday(&t1,NULL);
std::cout << (t1-t0) << std::endl;
std::cout << "\t\t\t\t\t\t\tForce check" << z4s[sample][2] << std::endl;
return -1;
}
你是如何編譯的? – Joel
g ++ -O3 -I/usr/include/eigen3。我在Linux 14.04上,3.2.0 Eigen和4.8.4 gcc。我也在同一臺電腦上獲得類似的結果與鐺。 – NMsd
我無法複製。生成的ASM對於每個版本都完全相同。你可以用'g ++ -O3 -DNDEBUG -s'自己檢查並在生成的asm文件中搜索'sumCols'和'sumVec'。 – ggael