【问题标题】:gfortran and ifort gives different resultsgfortran 和 ifort 给出不同的结果
【发布时间】:2018-06-12 09:13:33
【问题描述】:

我正在编写一个小代码,它将从 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 上。 提前致谢。

【问题讨论】:

  • 请包含文件2.txt(而不是图像)。 “但如果只是代码几次”是什么意思。您正在使用哪些编译标志(和编译器版本)。闻起来有点像未初始化的变量。
  • “但如果只是代码多次”:抱歉打错了。应该是“但如果只是多次运行代码”。
  • @albert 我没有使用任何编译标志。对于 gfortran,我使用的是 6.3.0 版本,对于 ifort,我使用的是 18.0.2。
  • 编译时示例立即崩溃。最好是首先开始检查输入是否是您期望的。语句read(999,*) x1(i,j) 读取完整的行并仅存储该行的第一个元素。不需要read(999,*) 行。也许qhestep 应该被初始化,但也要检查你使用的索引。
  • 也许全局 qhestep 而不是本地 qhestep 或本地保存 qhestep 可能会做一些好事。

标签: fortran gfortran intel-fortran fortran95


【解决方案1】:

两个编译器都应该给出垃圾结果,因为您正在为每个 DO k 循环分配扩散中的 qhestep。在退出扩散时,qhestep 被释放,因此累积的信息应该丢失。 ifort 在每次调用时为 qhestep 返回相同的堆地址是误导性的。

为了克服这个问题,你应该在进入 DO k 循环之前使用 allocate (qhestep(nstep,nheatoms)),然后在调用扩散中调用累积数组。

不幸的是,ifort 给出了您的预期结果,因为它掩盖了一个重大的逻辑错误。每个 ALLOCATE 基本上都为数组提供了一个新的内存位置。

您在读取文件时也不提供错误测试。我建议使用 iostat= 进行读取,并在读取数据时报告数据。

总而言之,您的方法给出了两个编译器都提供的错误结果。您提供的 ifort 结果在某些情况下也是错误的,但在其他情况下是正确的,这具有误导性。

【讨论】:

  • 谢谢。你是对的,如果我在主程序中分配 qhestep 并将其传递给子程序扩散,那么代码在 ifort 和 gfortran 中都可以正常工作。如果我还在子程序扩散中本地保存 qhestep,那么它也可以按预期工作,正如 albert 所建议的那样。
猜你喜欢
  • 1970-01-01
  • 2012-07-12
  • 2021-09-25
  • 2023-03-30
  • 1970-01-01
  • 2011-04-03
  • 2015-08-26
  • 2021-12-25
  • 1970-01-01
相关资源
最近更新 更多