gfortran 和 ifort 给出不同的结果
gfortran and ifort gives different results
我正在编写一个小代码,它将从 2.txt 中读取数字,这是一堆随机实数,将其保存在二维数组中并将其传递给子程序。在子例程中,我将这个数组的特定维度分配给另一个矩阵以保存它以供将来计算。
implicit none
double precision, allocatable :: x1(:,:)
integer :: nstep, nheatoms, k, i, j
open(unit=999,file="2.txt",status="old")
nstep = 5
nheatoms = 2
allocate(x1(3,nheatoms))
do k = 1, nstep
do i = 1, 3
do j = 1, nheatoms
read(999,*) x1(i,j)
end do
read(999,*)
end do
call diffusion(nstep,nheatoms,x1)
end do
stop
end
subroutine diffusion(nstep,nheatoms,qhecent)
implicit none
integer, intent (in) :: nheatoms, nstep
double precision :: qhecent(3,nheatoms)
integer :: j
double precision, allocatable :: qhestep(:,:)
integer :: nstepdiff, ncross
integer, save :: l = 0
double precision :: diff
l = l + 1
allocate(qhestep(nstep,nheatoms))
do j = 1, nheatoms
qhestep(l,j) = qhecent(3,j)
end do
if (l .gt. 1) then
do j = 1, nheatoms
write(*,*)qhestep(l,j), qhestep(l-1,j)
end do
end if
end subroutine
2.txt文件如下:
1.0
2.1
3.2
-1.1
-2.2
-3.3
5.0
3.5
4.4
1.9
2.1
1.5
6.0
3.5
4.4
1.9
2.8
2.5
6.0
3.5
4.4
1.9
2.1
3.2
6.0
3.5
4.4
1.9
-4.3
7.9
现在如果我用 gfortran 编译,大多数时候我得到的输出是:
2.1000000000000001 -2.2000000000000002
1.5000000000000000 -3.2999999999999998
2.7999999999999998 2.1000000000000001
2.5000000000000000 1.5000000000000000
2.1000000000000001 2.7999999999999998
3.2000000000000002 2.5000000000000000
-4.2999999999999998 2.1000000000000001
7.9000000000000004 3.2000000000000002
这是预期的。但是如果我多次 运行 代码,输出中会出现未知数字,例如示例:
2.1000000000000001 -2.2000000000000002
1.5000000000000000 -3.2999999999999998
2.7999999999999998 1.2882297539194267E-231
2.5000000000000000 0.0000000000000000
2.1000000000000001 2.7999999999999998
3.2000000000000002 2.5000000000000000
-4.2999999999999998 2.1000000000000001
7.9000000000000004 3.2000000000000002
如果我用 ifort 编译,那么我得到的输出有两个零,这是错误的。
2.10000000000000 -2.20000000000000
1.50000000000000 -3.30000000000000
2.80000000000000 0.000000000000000E+000
2.50000000000000 0.000000000000000E+000
2.10000000000000 2.80000000000000
3.20000000000000 2.50000000000000
-4.30000000000000 2.10000000000000
7.90000000000000 3.20000000000000
我必须强调,大部分时间在 ifort 上编译都会给出正确的结果,就像在 gfortran 上一样。我在 Mac OS High Sierra 上。
提前致谢。
两个编译器都应该给出垃圾结果,因为您正在为每个 DO k 循环分配扩散中的 qhestep。在退出扩散时,qhestep 被释放,所以积累的信息应该丢失。 ifort returns 每次调用时 qhestep 的相同堆地址具有误导性。
为了克服这个问题,你应该在进入DO k循环之前使用allocate(qhestep(nstep,nheatoms)),然后在call diffusion中传递累加数组。
不幸的是,ifort 给出了您预期的结果,因为它掩盖了一个重大的逻辑错误。每个 ALLOCATE 基本上为数组提供一个新的内存位置。
您在读取文件时也没有提供错误测试。我建议使用 iostat= 进行读取,并在读取时报告数据。
总而言之,您的方法给出了两个编译器都提供的错误结果。你提供的ifort结果在某些情况下也是错误的,但在其他情况下是正确的,这是误导。
我正在编写一个小代码,它将从 2.txt 中读取数字,这是一堆随机实数,将其保存在二维数组中并将其传递给子程序。在子例程中,我将这个数组的特定维度分配给另一个矩阵以保存它以供将来计算。
implicit none
double precision, allocatable :: x1(:,:)
integer :: nstep, nheatoms, k, i, j
open(unit=999,file="2.txt",status="old")
nstep = 5
nheatoms = 2
allocate(x1(3,nheatoms))
do k = 1, nstep
do i = 1, 3
do j = 1, nheatoms
read(999,*) x1(i,j)
end do
read(999,*)
end do
call diffusion(nstep,nheatoms,x1)
end do
stop
end
subroutine diffusion(nstep,nheatoms,qhecent)
implicit none
integer, intent (in) :: nheatoms, nstep
double precision :: qhecent(3,nheatoms)
integer :: j
double precision, allocatable :: qhestep(:,:)
integer :: nstepdiff, ncross
integer, save :: l = 0
double precision :: diff
l = l + 1
allocate(qhestep(nstep,nheatoms))
do j = 1, nheatoms
qhestep(l,j) = qhecent(3,j)
end do
if (l .gt. 1) then
do j = 1, nheatoms
write(*,*)qhestep(l,j), qhestep(l-1,j)
end do
end if
end subroutine
2.txt文件如下:
1.0
2.1
3.2
-1.1
-2.2
-3.3
5.0
3.5
4.4
1.9
2.1
1.5
6.0
3.5
4.4
1.9
2.8
2.5
6.0
3.5
4.4
1.9
2.1
3.2
6.0
3.5
4.4
1.9
-4.3
7.9
现在如果我用 gfortran 编译,大多数时候我得到的输出是:
2.1000000000000001 -2.2000000000000002
1.5000000000000000 -3.2999999999999998
2.7999999999999998 2.1000000000000001
2.5000000000000000 1.5000000000000000
2.1000000000000001 2.7999999999999998
3.2000000000000002 2.5000000000000000
-4.2999999999999998 2.1000000000000001
7.9000000000000004 3.2000000000000002
这是预期的。但是如果我多次 运行 代码,输出中会出现未知数字,例如示例:
2.1000000000000001 -2.2000000000000002
1.5000000000000000 -3.2999999999999998
2.7999999999999998 1.2882297539194267E-231
2.5000000000000000 0.0000000000000000
2.1000000000000001 2.7999999999999998
3.2000000000000002 2.5000000000000000
-4.2999999999999998 2.1000000000000001
7.9000000000000004 3.2000000000000002
如果我用 ifort 编译,那么我得到的输出有两个零,这是错误的。
2.10000000000000 -2.20000000000000
1.50000000000000 -3.30000000000000
2.80000000000000 0.000000000000000E+000
2.50000000000000 0.000000000000000E+000
2.10000000000000 2.80000000000000
3.20000000000000 2.50000000000000
-4.30000000000000 2.10000000000000
7.90000000000000 3.20000000000000
我必须强调,大部分时间在 ifort 上编译都会给出正确的结果,就像在 gfortran 上一样。我在 Mac OS High Sierra 上。 提前致谢。
两个编译器都应该给出垃圾结果,因为您正在为每个 DO k 循环分配扩散中的 qhestep。在退出扩散时,qhestep 被释放,所以积累的信息应该丢失。 ifort returns 每次调用时 qhestep 的相同堆地址具有误导性。
为了克服这个问题,你应该在进入DO k循环之前使用allocate(qhestep(nstep,nheatoms)),然后在call diffusion中传递累加数组。
不幸的是,ifort 给出了您预期的结果,因为它掩盖了一个重大的逻辑错误。每个 ALLOCATE 基本上为数组提供一个新的内存位置。
您在读取文件时也没有提供错误测试。我建议使用 iostat= 进行读取,并在读取时报告数据。
总而言之,您的方法给出了两个编译器都提供的错误结果。你提供的ifort结果在某些情况下也是错误的,但在其他情况下是正确的,这是误导。