5

在尝试在一个简单的程序中混合精度 - 使用实数和双精度 - 并使用 BLAS 的 ddot 例程,我为双精度部分提出了不正确的输出。这是代码:

program test

!! adding this statement narrowed the issue down to ddot being considered real(4)
implicit none

integer, parameter :: dp = kind(1.0d0)

!! The following 2 lines were added for the calls to the BLAS routines.
!! This fixed the issue.
real(dp), external :: ddot
real, external :: sdot

real, dimension(3) :: a,b
real(dp), dimension(3) :: d,e

integer :: i

do i = 1,3
    a(i) = 1.0*i
    b(i) = 3.5*i
    d(i) = 1.0d0*i
    e(i) = 3.5d0*i
end do

write (*,200) "sdot real(4) = ", sdot(3,a,1,b,1)  ! should work and return 49.0
write (*,200) "ddot real(4) = ", ddot(3,a,1,b,1)  ! should not work

write (*,200) "sdot real(8) = ", sdot(3,d,1,e,1)  ! should not work
write (*,200) "ddot real(8) = ", ddot(3,d,1,e,1)  ! should work and return 49.0

200 format(a,f5.2)

end program test

我尝试使用 MKL BLAS 库同时编译 gfortran 和 ifort,如下所示:

ifort -lmkl_intel_lp64 -lmkl_sequential -lmkl_core

gfortran -lmkl_intel_lp64 -lmkl_sequential -lmkl_core main.f90

输出是:

sdot real(4) = 49.00
ddot real(4) =  0.00
sdot real(8) =  4.10
ddot real(8) =  0.00

如何让 ddot 例程正确处理双精度值?

此外,添加 -autodouble 标志 (ifort) 或 -fdefault-real-8 (gfortran) 标志会使两个 ddot 例程都工作,但 sdot 例程会失败。

编辑: 我添加了隐式 none 语句,以及 ddot 和 sdot 函数的两个类型语句。如果没有为函数调用指定类型,则 ddot 被隐式键入为单精度实数。

4

2 回答 2

6

我没有使用过 MKL,但也许您需要一个“使用”语句,以便编译器知道函数的接口?或者以其他方式声明函数。它们没有被声明,因此编译器可能假设 ddot 的返回是单精度的并且错误地解释了这些位。

打开警告选项会导致编译器告诉您问题。使用 gfortran,尝试: -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file -fcheck=all -std=f2008 -pedantic -fbacktrace

于 2011-05-08T06:04:02.703 回答
2

传递不正确的类型变量是接口不匹配的情况(这是非法的,因此原则上编译器可能会做任何事情,包括启动 WW III),所以这可能会弄乱堆栈,因此后续调用也会返回不正确的结果。尝试注释掉那些不正确的调用(你的行标有“不应该工作”),看看是否有帮助。

此外,启用您可以找到的各种调试选项,例如 MSB 为 gfortran 显示的答案。

于 2011-05-08T06:27:21.237 回答