2014-11-24 106 views
1

我只用LAPACK/BLAS運行一次矩陣*矩陣乘法,並且用自定義循環優化(平鋪)運行一次。我有點惱火,因爲簡單的循環平鋪方法比BLAS算法快大約43%。基本上,我的問題是我是否在應用BLAS例程時犯了一個錯誤。這裏是我的代碼:LAPACK/BLAS sgemm()比自定義矩陣乘法要慢

program test 
    implicit none 

    integer, parameter :: N = 1000, tile = 2 
    real*4, dimension(N,N) :: a,b,c,temp 
    integer :: i,j,k,x,y,z 
    double precision :: E,S 
    real :: alpha = 1.0, beta = 0.0 

    call random_seed() 
    call random_number(a) 
    call random_number(b) 

    call cpu_time(S) 

    ! call sgemm('n','n',N, N, N, alpha,a,N,b,N, beta,c,N) 

    do j = 1,N,tile 
    do k = 1,N,tile 
     do i = 1,N,tile 
      do y = j, min(j+tile-1,N) 
       do x = i, min(i+tile-1,N) 
       do z = k, min(k+tile-1,N) 
        c(x,y) = c(x,y) + a(x,z) * b(z,y) 
       enddo 
       enddo 
      enddo 
     enddo 
    enddo 
    enddo 

    call cpu_time(E) 
    print*,(E-S) 
end program test 

我運行一個英特爾雙酷睿2機4GB DRAM和3096kb緩存這種計算。程序編譯時:

$gfortran -O3 test.f03 -o test 
0.9359 

爲循環和:

$gfortran test.f03 -lblas -O3 -o test 
1.3399 

所以我是沒有得到一些關於BLAS,我失去的東西(編譯優化,或好,我只是不知道什麼)?我用C++運行了一個類似的代碼,不管Eigen :: Matrix,並且使用Eigen庫來獲得相當大的收益,這就是爲什麼我的期望與BLAS庫相似的原因。

回答

1

BLAS程序正確使用。 唯一的區別是,BLAS正在執行

C = 0.0*C + 1.0*A*B 

和你的循環

C = C + A*B 

在你的循環,你正在試圖提高CPU的緩存內存的使用。 BLAS有多種變體可以執行類似的操作。 我建議你嘗試openblas,atlas或mkl(intel編譯器)庫。你會得到很大的時間改善。

+0

我看到謝謝你的評論。我並不確定,因爲我剛剛開始使用該庫,並對文檔感到困惑。但如果我正確實施它,那就沒問題。再次感謝。 – Vincent 2014-11-24 13:17:12

+0

順便說一下你能推薦一個好的ATLAS文檔嗎? – Vincent 2014-11-24 15:13:35

+0

ATLAS代表自動調諧庫。用法與BLAS相同。只需下載並編譯到您的PC。另外openblas是一個非常活躍的項目。也很容易建立。 – ztik 2014-11-24 15:46:12