簡體   English   中英

Eigen vs Matlab:並行化矩陣乘法

[英]Eigen vs Matlab: parallelized Matrix-Multiplication

我想比較矩陣乘法中Matlab的速度與Intel(R)Core(TM)i7-4770 CPU @ 3.40GHz上的Eigen 3的速度。 代碼包括Eigen

#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我正在使用

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

結果是: Matlab為9s, Eigen36s 我在Eigen案中做錯了什么? 我可以排除矩陣的動態分配。 此外,僅使用3個線程而不是8個線程。

編輯

也許我沒有說得足夠清楚:任務是乘以10000倍dim = 100的雙值矩陣, 每次隨機填充,不僅一次。 使用Eigen盡可能快地完成。 如果Eigen不能應付Matlab,你會建議什么選擇?

下面是一個更好的代碼版本,可以合理地使用Eigen。 總結一下:

  • setRandom()移到基准測試循環之外。 setRandom()調用系統rand()函數,這個函數相當慢。
  • 使用.noalias()來避免創建臨時(僅當右側是產品時才有意義)
  • 將OMP_NUM_THREADS設置為真正的核心數,而不是超線程數。 (在你的情況下為4)
  • 你的CPU支持只有Eigen的devel分支支持的AVX和FMA(將變為3.3),所以使用devel分支並使用-mavx-mfma編譯器選項啟用它們(與僅SSE相比,約為-mfma加速) )

編碼:

#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;
}

除了環(在兩個本征和Matlab)以外移動隨機化,如ggael建議的,取代parforfor在Matlab因為在本征代碼您處理矩陣順序。

我不確定Matlab如何並行化其代碼:也許多個線程在同一對矩陣上工作,並在完成時切換到下一個矩陣; 也許每個線程處理它自己的一對矩陣。 可以說后者可能更快,因為更好地使用核心特定的緩存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM