LAPACK / BLAS sgemm()比自定义矩阵乘法慢

时间:2014-11-24 12:30:57

标签: matrix-multiplication blas

我刚用LAPACK / BLAS运行一次矩阵*矩阵乘法,用自定义循环优化(平铺)运行一次。我有点恼火,因为简单的循环平铺方法比BLAS算法快约43%。基本上,我的问题是我是否在应用BLAS例程时犯了错误。这是我的代码:

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

我在具有4gb DRAM和3096kb Cache的Intel Dual Core2机器上运行此计算。该程序编译为:

$gfortran -O3 test.f03 -o test
0.9359

表示循环并且:

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

所以我没有得到关于BLAS的东西,我错过了什么(编译器优化,或者我只是不知道什么)?我在使用和不使用Eigen :: Matrix的情况下使用C ++运行了类似的代码,并且从使用MMM的特征库获得了相当大的收益,这就是为什么我的期望与BLAS库类似的高。

1 个答案:

答案 0 :(得分:1)

正确使用BLAS例程。 唯一的区别是BLAS正在执行

C = 0.0*C + 1.0*A*B

和你的循环

C = C + A*B

在你的循环中,你试图提高cpu缓存的使用率。 BLAS的变体执行类似的操作。 我建议你尝试openblas,atlas或mkl(intel编译器)库。你会得到很好的时间改进。