2017-12-19 11 views
1

私はC++とnumpyを使って固有値の行列乗算性能を比較しようとしています。ここでは、Pythonコードが行列の乗算性能numpyと固有のC++

time = 0.116 seconds

次のとおりです。ここで

g++ -Wall -Wextra -I "path-to-eigen-directory" prog5.cpp -o prog5 -O3 -std=gnu++0x

出力を使用してコンパイルするマトリックス乗算

#include<iostream> 
#include <Eigen/Dense> 
#include <ctime> 
#include <iomanip> 

using namespace Eigen; 
using namespace std; 


    int main() 
{ 
    time_t begin,end; 
    double difference=0; 
    time (&begin); 
    for(int i=0;i<500;++i) 
    { 
    MatrixXd m1 = MatrixXd::Random(500,500); 
    MatrixXd m2 = MatrixXd::Random(500,500); 
    MatrixXd m3 = MatrixXd::Zero(500,500); 
    m3=m1*m2; 
    } 
    time (&end); 
    difference = difftime (end,begin); 
    std::cout<<"time = "<<std::setprecision(10)<<(difference/500.)<<" seconds"<<std::endl; 

    return 0; 
} 

のためのC++コードです。

import timeit 
import numpy as np 

start_time = timeit.default_timer() 
for i in range(500): 

    m1=np.random.rand(500,500) 
    m2=np.random.rand(500,500) 
    m3=np.zeros((500,500)) 
    m3=np.dot(m1,m2) 

stop_time = timeit.default_timer() 
print('Time = {} seconds'.format((stop_time-start_time)/500)) 

出力:

Time = 0.01877937281645333 seconds

C++コードは、Pythonに比べて6倍遅いように見えます。誰かが私がここに何かを欠いているかどうか洞察を与えることができます

私はEigen 3.3.4、g ++コンパイラ(MinGW.org GCC-6.3.0-1)6.3.0、python 3.6.1、numpy 1.11.3を使用しています。 spyder ideで動作するPython。 Windowsの使用。

更新:答えとコメントを1として

、私は、コードを更新しました。

g++ -Wall -Wextra -I "path-to-eigen-directory" prog5.cpp -o prog5 -O3 -std=gnu++0x -march=nativeでコンパイルされたC++コード。 -fopenmpを動作させることができませんでした。このフラグを使用すると出力がないようです。

#include<iostream> 
#include <Eigen/Dense> 
#include <ctime> 
#include <iomanip> 

using namespace Eigen; 
using namespace std; 

int main() 
{ 
    time_t begin,end; 
    double difference=0; 
    time (&begin); 
    for(int i=0;i<10000;++i) 
    { 
    MatrixXd m1 = MatrixXd::Random(500,500); 
    MatrixXd m2 = MatrixXd::Random(500,500); 
    MatrixXd m3 = MatrixXd::Zero(500,500); 
    m3=m1*m2; 
    } 
    time (&end); // note time after execution 
    difference = difftime (end,begin); 
    std::cout<<"Total time = "<<difference<<" seconds"<<std::endl; 
    std::cout<<"Average time = "<<std::setprecision(10)<<(difference/10000.)<<" seconds"<<std::endl; 

    return 0; 
} 

出力:

Total time = 328 seconds 
Average time = 0.0328 seconds 

Pythonコード:

import timeit 
import numpy as np 

start_time = timeit.default_timer() 
for i in range(10000): 

    m1=np.random.rand(500,500) 
    m2=np.random.rand(500,500) 
    m3=np.zeros((500,500)) 
    m3=np.dot(m1,m2) 

stop_time = timeit.default_timer() 
print('Total time = {} seconds'.format(stop_time-start_time)) 
print('Average time = {} seconds'.format((stop_time-start_time)/10000)) 

はスパイダーのIDEを使用してrunfile('filename.py')コマンドを実行します。

出力:

Total time = 169.35587796526667 seconds 
Average time = 0.016935587796526666 seconds 

は今固有のパフォーマンスは優れているが、に等しいか、またはnumpyのより速くありません。 -fopenmpかもしれませんが、トリックを行うことができますが、わからない。しかし暗黙的にそうしていない限り、私はnumpyで並列化を使用していません。

+0

数分間テストを実行します。あなたが提供した時間は統計的には健全ではありません。 – Serge

+0

質問が更新されました。 – vcx34178

+0

行列の乗算は、使用しているBLAS/Linpackライブラリに大きく依存します。 numpyとeigenのどちらを使うかを追加する必要があります。 (例えばインテルMKL) – max9111

答えて

1

あなたのベンチマークにはいくつかの問題があります。

  1. あなたは非常に高価であるシステムrand()機能をベンチマーキングしています!
  2. AVX/FMAのブーストを得るためにコンパイラが見つからない
  3. マルチスレッドを有効にするために-fopenmpが不足しています。

私のクワッドi7 2。6GHz CPU私は次のようになります:

initial code:      0.024s 
after replacing `Random` by `Ones`: 0.018s 
adding `-march=native`:    0.006s 
adding `-fopenmp`:     0.003s 

マトリックスは、多すぎるとマルチスレッド化の利点が得られません。

+0

(1)私はPythonコードで 'rand()'を使用していますので、(実際には)それにもコストがかかるはずです。 (2) '-march = native'で質問を更新しました。残念ながら、残念ながら '-fopenmp'を実行することができませんでした – vcx34178

+0

しかし、pythonのrand()が高速になる可能性がありますので、このソースを削除するために' Random'を 'Ones'で置き換えて確認してください。 。私の誕生日は4歳ですから、似たようなパフォーマンスが得られるはずです。私たちは現在、5より大きいファクタを観察しています(openmpがなくても)、あなたの側に何か間違っているはずです。 – ggael