fortran blas openblas

fortran - OpenBLAS más lento que la función intrínseca dot_product



(1)

Necesito hacer un producto de puntos en Fortran. Puedo hacer con la función intrínseca dot_product de Fortran o usar ddot desde OpenBLAS. El problema es que el ddot es más lento. Este es mi código:

Con BLAS:

program VectorBLAS ! time VectorBlas.e = 0.30s implicit none double precision, dimension(3) :: b double precision :: result double precision, external :: ddot integer, parameter :: LargeInt_K = selected_int_kind (18) integer (kind=LargeInt_K) :: I DO I = 1, 10000000 b(:) = 3 result = ddot(3, b, 1, b, 1) END DO end program VectorBLAS

Con dot_product

program VectorModule ! time VectorModule.e = 0.19s implicit none double precision, dimension (3) :: b double precision :: result integer, parameter :: LargeInt_K = selected_int_kind (18) integer (kind=LargeInt_K) :: I DO I = 1, 10000000 b(:) = 3 result = dot_product(b, b) END DO end program VectorModule

Los dos códigos se compilan usando:

gfortran file_name.f90 -lblas -o file_name.e

¿Qué estoy haciendo mal? BLAS no tiene que ser más rápido?


Mientras que BLAS, y especialmente las versiones optimizadas, son generalmente más rápidas para las matrices más grandes, las funciones integradas son más rápidas para tamaños más pequeños.

Esto es especialmente visible desde el código fuente vinculado de ddot , donde se gasta trabajo adicional en funcionalidades adicionales (por ejemplo, diferentes incrementos). Para longitudes de matriz pequeñas, el trabajo realizado aquí supera la ganancia de rendimiento de las optimizaciones.

Si aumenta sus vectores (mucho), la versión optimizada debería ser más rápida.

Aquí hay un ejemplo para ilustrar esto:

program test use, intrinsic :: ISO_Fortran_env, only: REAL64 implicit none integer :: t1, t2, rate, ttot1, ttot2, i real(REAL64), allocatable :: a(:),b(:),c(:) real(REAL64), external :: ddot allocate( a(100000), b(100000), c(100000) ) call system_clock(count_rate=rate) ttot1 = 0 ; ttot2 = 0 do i=1,1000 call random_number(a) call random_number(b) call system_clock(t1) c = dot_product(a,b) call system_clock(t2) ttot1 = ttot1 + t2 - t1 call system_clock(t1) c = ddot(100000,a,1,b,1) call system_clock(t2) ttot2 = ttot2 + t2 - t1 enddo print *,''dot_product: '', real(ttot1)/real(rate) print *,''BLAS, ddot: '', real(ttot2)/real(rate) end program

Las rutinas BLAS son bastante más rápidas aquí:

OMP_NUM_THREADS=1 ./a.out dot_product: 0.145999998 BLAS, ddot: 0.100000001