2015-02-02 3 views
7
I는 인텔 (R) 코어 (TM)에 아이겐 3의 속도 매트릭스 곱셈에 의 matlab에를 속도 비교하고자

i7-4770 CPU에서 @의 3.40GHz . 아이겐 포함 코드 :matlab에 대 아이겐 : 병렬 행렬 승산

#include <iostream> 
#include "Eigen/Dense" 
#include <chrono> 
#include <omp.h> 


using namespace std; 
using namespace Eigen; 

const int dim=100; 

int main() 
{ 
    std::chrono::time_point<std::chrono::system_clock> start, end; 

    int n; 
    n = Eigen::nbThreads(); 
    cout<<n<<"\n"; 

    Matrix<double, Dynamic, Dynamic> m1(dim,dim); 
    Matrix<double, Dynamic, Dynamic> m2(dim,dim); 
    Matrix<double, Dynamic, Dynamic> m_res(dim,dim); 

    start = std::chrono::system_clock::now(); 

    for (int i = 0 ; i <100000; ++i) { 
     m1.setRandom(dim,dim); 
     m2.setRandom(dim,dim); 
     m_res=m1*m2; 

    } 

    end = std::chrono::system_clock::now(); 
    std::chrono::duration<double> elapsed_seconds = end-start; 

    std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; 

    return 0; 
} 

g++ -O3 -std=c++11 -fopenmp로 컴파일 및 OMP_NUM_THREADS=8 ./prog 실행됩니다. matlab에, 에 대한 36S 아이겐에 대한 9S : matlab에 나는

function mat_test(N,dim) 
% 
% N: how many tests 
% dim: dimension of the matrices 

tic 
parfor i=1:N 
    A = rand(dim); 
    B = rand(dim); 
    C = A*B; 
end 
toc 

결과를 사용하고 있습니다. Eigen 케이스에서 내가 뭘 잘못하고 있니? 행렬의 동적 할당을 제외 할 수 있습니다. 또한 8 개 대신 3 개의 스레드 만 사용됩니다.

편집 :

어쩌면 내가 충분히 명확하게 그것을 언급하지 않았다는 :이 작업은 이중 무작위로뿐만 아니라 한 번, 마다을 가득 100 = 희미한의 행렬을 평가 100000times을 곱하는 것입니다. 아이겐 (Eigen)과 함께 가능한 한 빨리하십시오. Eigen이 Matlab에 대처할 수 없다면 어떤 선택을 제안합니까?

+1

당신은 실제로 무엇을 비교하려고합니까? 매트릭스 곱셈과 함께 난수 생성 시간을 측정하고 있습니다. Eigen은 다른 훨씬 느린 난수 생성기를 사용할 수 있습니다. 또한 타이밍을 시작하기 전에 Matlab에서 배열을 사전 할당하지 않아도됩니다. 각 부분의 프로파일 링 또는 타이밍을 제안합니다. 먼저 OMP /'parfor '를 사용하지 않고 두개를 비교해 보았습니까? 마지막으로 왜 아이겐 (Eigen)이 더 느리기 때문에 당신이 뭔가 잘못하고 있다고 생각합니까? – horchler

+2

Eigen의 고정 된 크기의 행렬을 비교합니다. matlab에서 지연 계산을 사용하면 'C'가 사용될 때까지 'A * B'를 할 필요가 없으며 'C'를 사용하지 않으므로 곱셈을 제거 할 수 있습니다. C++에서 이것을 에뮬레이션 할 수 있습니다.'auto res = std :: async (std :: launch :: deferred, [&] {return m1 * m2;});'. 음, 공유 포인터에 불변의 행렬을 사용하고 지연 테스트 (게으른 행렬뿐만 아니라)를 사용하여'*'를 구현하고 있습니까? 요약하면, 의미있게 비교할 무언가를해야합니다. – Yakk

+0

CPU에는 코어가 4 개만 있으므로 OMP_NUM_THREADS = 4로 실행하십시오. 하이퍼 스레딩은 이미 CPU 리소스의 99 %를 이용하는 고도로 최적화 된 코드와 호환되지 않습니다. 반면 CPU는 AVX와 FMA를 지원하므로 Eigen의 devel 분기를 다운로드하고 -mavx 및 -mfma를 사용하여 컴파일하십시오. – ggael

답변

4

다음은 Eigen을 올바르게 사용하는 코드의 더 나은 버전입니다. 요약하려면 다음을 수행하십시오.

  • setRandom()을 벤치마킹 루프 외부로 이동하십시오. setRandom()은 다소 느린 시스템 rand() 기능을 호출합니다. 코어의 실제 수없는 하이퍼 스레드 번호
  • 세트 OMP_NUM_THREADS 임시의 생성을 방지하기
  • 사용 .noalias()은 (오른쪽 측 제품 일 경우에만 의미가). (귀하의 경우 4)
  • CPU가 Eigen의 devel 분기 (3.3이 됨)에서만 지원되는 AVX 및 FMA를 지원하므로 devel 분기를 사용하여 -mavx-mfma 컴파일러 옵션 (x3에 해당)으로 활성화하십시오. SSE에 비해 5 속도까지만)

코드 :

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

using namespace std; 
using namespace Eigen; 

const int dim=100; 

int main() 
{ 
    std::chrono::time_point<std::chrono::system_clock> start, end; 

    int n; 
    n = Eigen::nbThreads(); 
    cout << n << "\n"; 

    Matrix<double, Dynamic, Dynamic> m1(dim,dim); 
    Matrix<double, Dynamic, Dynamic> m2(dim,dim); 
    Matrix<double, Dynamic, Dynamic> m_res(dim,dim); 

    start = std::chrono::system_clock::now(); 

    m1.setRandom(); 
    m2.setRandom(); 

    for (int i = 0 ; i <100000; ++i) { 
     m_res.noalias() = m1 * m2; 
    } 

    end = std::chrono::system_clock::now(); 
    std::chrono::duration<double> elapsed_seconds = end-start; 

    std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; 

    return 0; 
} 
+1

은 setRandom을 항상 갖기 때문에 코드가 단순히 곱셈을 타이밍하는 것이 아니라는 것을 의미합니다. – Goz

+1

비슷한 속도로 MATLAB 코드에서와 똑같이 할 수있는 방법이 있습니까? 매트릭스 곱셈은 아니지만 C++ 코드에서 무작위 추출을 한 번만 수행하면 Matlab에서 수행되는 작업이 아니라는 것을 알 수 있습니다. 즉 : matlabs 코드와 경쟁 할 수있는 임의의 생성기가 있습니까? –

+0

질문을 명확히하십시오. 매우 빠른 난수 생성기 또는 고속 행렬 곱셈을 찾으십니까? 빠른 난수를 찾고 있다면 발전기의 품질과 속도 사이에 일반적으로 상충 관계가 있으므로 요구 사항을 지정하십시오. – ggael

0

아이겐 Matlab과) 모두 (루프 밖에 랜덤 이동 외에 ggael 제안으로서, 매트랩 for으로 parfor을 바꿀 때문에 순열 행렬을 처리하는 고유 코드 ially.

Matlab이 코드를 어떻게 병렬화했는지 모르겠습니다. 아마도 여러 스레드가 동일한 행 쌍에서 작동하고 완료되었을 때 다음 행으로 전환 할 수 있습니다. 어쩌면 각 스레드는 자체 행렬 쌍을 처리합니다. 코어 특정 캐시를 더 잘 사용하기 때문에 후자가 더 빠를 수도 있다고 주장 할 수 있습니다.