Fortran的MKL dgemm没有结果

时间:2017-06-27 06:20:07

标签: fortran matrix-multiplication blas intel-mkl

在下面的Fortran程序中,我使用Intel的MKL库使用dgemm执行矩阵乘法。最初,我使用matmul子例程并得到了正确的结果。当我在下面的循环中将matmul翻译为dgemm时,我获得了所有零向量而不是正确的输出。感谢您的帮助。

program spectral_norm    
implicit none
!
integer, parameter :: n = 5500, dp = kind(0.0d0)
real(dp), allocatable :: A(:, :), u(:), v(:), Au(:), Av(:)
integer :: i, j

allocate(u(n), v(n), A(n, n), Au(n), Av(n))

do j = 1, n
    do i = 1, n
        A(i, j) = Ac(i, j)
    end do
end do

u = 1
do i = 1, 10
    call dgemm('N','N', n, 1, n, 1.0, A,  n, u, n, 0.0, Au, n) 
    call dgemm('N','N', n, 1, n, 1.0, Au, n, A, n, 0.0, v,  n) 
    call dgemm('N','N', n, 1, n, 1.0, A,  n, v, n, 0.0, Av, n) 
    call dgemm('N','N', n, 1, n, 1.0, Av, n, A, n, 0.0, u,  n) 
    !v = matmul(matmul(A, u), A)
    !u = matmul(matmul(A, v), A)
end do

write(*, "(f0.9)") sqrt(dot_product(u, v) / dot_product(v, v))

contains

pure real(dp) function Ac(i, j) result(r)
integer, intent(in) :: i, j
r = 1._dp / ((i+j-2) * (i+j-1)/2 + i)
end function

end program spectral_norm

这会NaN,而matmul的正确输出为1.274224153

1 个答案:

答案 0 :(得分:0)

好的,谢谢大家的建议。我想我找出了错误的来源。在两种情况下,乘法的顺序相反,它应该是<?php $testing="70, 60, 60, 30"; $test=explode(",",$testing); function array_manipulation($array){ $final_val = 0; for($i=1;$i<=(count($array)-1);$i++){ $final_val += $array[$i]; } return $final_val-$array[0]; } echo array_manipulation($test); ?> A * Au。这是因为A * Av订单A,而n x nAu都有订单Av。因此,由于尺寸不匹配,我们无法乘以n x 1Au * A。我在下面发布了更正后的版本。

Av * A

这给出了正确的结果:

program spectral_norm    
implicit none
!
integer, parameter :: n = 5500, dp = kind(0.d0)
real(dp), allocatable :: A(:,:), u(:), v(:), Au(:), Av(:)
integer :: i, j

allocate(u(n), v(n), A(n, n), Au(n), Av(n))

do j = 1, n
    do i = 1, n
        A(i, j) = Ac(i, j)
    end do
end do

u = 1
do i = 1, 10
    call dgemm('N', 'N', n, 1, n, 1._dp, A, n, u,  n, 0._dp, Au, n)
    call dgemm('T', 'N', n, 1, n, 1._dp, A, n, Au, n, 0._dp, v,  n)
    call dgemm('N', 'N', n, 1, n, 1._dp, A, n, v,  n, 0._dp, Av, n)
    call dgemm('T', 'N', n, 1, n, 1._dp, A, n, Av, n, 0._dp, u,  n)
end do

write(*, "(f0.9)") sqrt(dot_product(u, v) / dot_product(v, v))

contains

pure real(dp) function Ac(i, j) result(r)
    integer, intent(in) :: i, j
    r = 1._dp / ((i+j-2) * (i+j-1)/2 + i)
end function

end program spectral_norm