在下面的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
。
答案 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 n
和Au
都有订单Av
。因此,由于尺寸不匹配,我们无法乘以n x 1
或Au * 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