2016-09-27 574 views
1

我想使用库Eigen来进行线性代数计算。特别是,我想用随机矩阵乘一个随机向量。这里是我使用的代码:与特征向量 - 矩阵相乘

#include <iostream> 
#include <chrono> 
#include <Eigen/Dense> 

using namespace Eigen; 

int main(){ 

    Eigen::initParallel(); 
    Matrix<unsigned int,Dynamic,Dynamic> A; A = Matrix<unsigned int,500,15500>::Random(); 
    Matrix<unsigned int,Dynamic, Dynamic> s; s= Matrix<unsigned int,1,500>::Random(); 
    Matrix<unsigned int,Dynamic,Dynamic> b; 

    auto t1 = std::chrono::high_resolution_clock::now(); 

    b=s*A; 

    auto t2 = std::chrono::high_resolution_clock::now(); 
    auto timeMult = std::chrono::duration_cast <std::chrono::microseconds>(t2 - t1).count(); 
    std::cout << "Result size: " << b.rows() << "x" << b.cols() << std::endl; 
    std::cout << "Time for multiplication: " << timeMult << " microseconds" << std::endl; 

    return 0; 
} 

然后,编译它,我做

g++ -I. -Wall -std=c++0x -fopenmp main.cpp 

我相信一切工作正常(我没有检查实际的结果),但它似乎很慢。为了给出一个想法,我写了一个C++代码,它完全相同,并且明确地使用了thread s,运行速度比我上面粘贴的代码快54倍!特别是在我的机器上,我的C++代码在5300微秒的时间内是286904微秒。

任何想法,为什么它如此之慢,以及如何使其更快?

编辑

我不是张贴我写的代码,因为它是一块更大的软件,并且制造出MWE它需要大量的工作。相反,我将描述它的作用:我定义了包含std::vector s的向量和矩阵的类,然后进行乘法运算,我定义了一定数量的thread s,将矩阵分成大块并且每个thread计算线性组合根据向量中的系数确定行的数量。每个thread将其部分结果写入另一行向量,最后将所有向量相加在一起以获得最终结果。很简单。顺便说一下,我使用了4 thread,尽管这个值可能会被优化。

+2

将'-O2'或'-O3'添加到编译命令中。 –

+0

@AviGinsburg谢谢!我很尴尬,我忘记了这个......无论如何用'-O2','-O3'或者甚至是'-Ofast',时间不会低于21500微秒,这仍然比我的代码慢4倍! – minomic

+0

小心发布你正在比较的代码吗? –

回答

2

此外,以增加-O2-O3到你的编译标志(在评论中指出的),你应该改变的sb类型Matrix<unsigned int,1,Dynamic>。如果Eigen在编译时知道产品的一个因素是矢量,它可以使用更快的产品实现。 在我的机器上,将执行时间从25392μs更改为4751μs。

但是,此刻您不会受益于矩阵向量产品的多线程(Eigen 3.3rc1)。

+0

好主意!我确认执行时间现在约为5300微秒,与我的C++代码完全相同。 – minomic

+1

使用Eigen 3.3,不要忘记'-march = native'来获得AVX加速。 – ggael