在尝试在一个简单的程序中混合精度 - 使用real和double - 并使用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将被隐式键入为单精度实数。
答案 0 :(得分:6)
我没有使用过MKL,但也许您需要一个“use”语句,以便编译器知道函数的接口?或以其他方式声明功能。它们未被声明,因此编译器可能假设ddot的返回是单精度并且错误地解释了这些位。
启用警告选项会使编译器告诉您该问题。使用gfortran,尝试: -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file -fcheck = all -std = f2008 -pedantic -fbacktrace
答案 1 :(得分:2)
传递错误的类型变量是接口不匹配的情况(这是非法的,所以原则上编译器可能会做任何事情,包括启动WW III),所以这可能会搞乱堆栈,因此跟随调用也会返回不正确的结果。尝试注释掉那些不正确的电话(标有“不应该工作”的行),看看是否有帮助。
此外,启用您可以找到的各种调试选项,例如: M.S.B.的答案。 gfortran的节目。