Fortran Coder

查看: 11132|回复: 9
打印 上一主题 下一主题

[数值问题] 请教下面这段代码的差异

[复制链接]

7

帖子

2

主题

0

精华

入门

F 币
53 元
贡献
28 点
跳转到指定楼层
楼主
发表于 2018-1-8 11:24:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大家好,我的程序里面有这么一段代码:

[Fortran] 纯文本查看 复制代码
     do j=1,nt
      ! csum=G_0t(j)
      do ic0=1,ndims
       ! CP0(j,ic0)=CP0(j,ic0)*csum
       CP0(j,ic0)=CP0(j,ic0)*G_0t(j)
      enddo
     enddo


其中 nt 是比较大的数,比如,640000。以上的代码可以 run。但是如果把上面的注释去掉,像下面这样:
[Fortran] 纯文本查看 复制代码
     do j=1,nt
      csum=G_0t(j)
      do ic0=1,ndims
       CP0(j,ic0)=CP0(j,ic0)*csum
       ! CP0(j,ic0)=CP0(j,ic0)*G_0t(j)
      enddo
     enddo


想来这样会减少对 G_0t 这个数组的内存的访问。但是这样会出现运行时错误,说 segmentation fault。

看起来这两种方式对内存的处理是不一样的。有没有高手帮我解释一下?

谢谢!
分享到:  微信微信
收藏收藏 点赞点赞 点踩点踩

490

帖子

4

主题

0

精华

大宗师

F 币
3298 元
贡献
1948 点

水王勋章元老勋章热心勋章

沙发
发表于 2018-1-8 11:51:27 | 只看该作者
csum没有定义吧?改成associate也出错?
[Fortran] 纯文本查看 复制代码
do j=1,nt
       associate(csum=>G_0t(j))then
      do ic0=1,ndims
       CP0(j,ic0)=CP0(j,ic0)*csum
      enddo
     end associate
     enddo

7

帖子

2

主题

0

精华

入门

F 币
53 元
贡献
28 点
板凳
 楼主| 发表于 2018-1-8 12:24:29 | 只看该作者
pasuka 发表于 2018-1-8 11:51
csum没有定义吧?改成associate也出错?
do j=1,nt
       associate(csum=>G_0t(j))then

谢谢。不过, csum 是声明成复数类型了的,因此应该不是这个原因

490

帖子

4

主题

0

精华

大宗师

F 币
3298 元
贡献
1948 点

水王勋章元老勋章热心勋章

地板
发表于 2018-1-8 13:17:24 | 只看该作者
本帖最后由 pasuka 于 2018-1-8 13:19 编辑
dypang 发表于 2018-1-8 12:24
谢谢。不过, csum 是声明成复数类型了的,因此应该不是这个原因

无法提供能够重现错误的最小代码,实在爱莫能助了
非涉密项目,可以考虑加入qq群,然后加群主好友,再远程桌面查看一下
本论坛官方QQ群:2338021

7

帖子

2

主题

0

精华

入门

F 币
53 元
贡献
28 点
5#
 楼主| 发表于 2018-1-9 13:48:10 | 只看该作者
pasuka 发表于 2018-1-8 13:17
无法提供能够重现错误的最小代码,实在爱莫能助了
非涉密项目,可以考虑加入qq群,然后加群主好友,再远程 ...

谢谢。我问这个问题只是想了解一下fortran的更细致的规则。这两段代码,一般情况下应该是一样的。可是,在我这里,第二种方式确实就会出现段错误。我怀疑是这两种方式对内存的操作是不一样的。但是这种错误大概只是在数组非常大的情况下才会出现。

7

帖子

2

主题

0

精华

入门

F 币
53 元
贡献
28 点
6#
 楼主| 发表于 2018-1-9 13:49:02 | 只看该作者
dypang 发表于 2018-1-9 13:48
谢谢。我问这个问题只是想了解一下fortran的更细致的规则。这两段代码,一般情况下应该是一样的。可是, ...

实际上,同样的程序,在 Linux 下面用第二种方式也是可以的,但是在 Windows 10 下面就不行。所以,应该跟操作系统也有关系。

490

帖子

4

主题

0

精华

大宗师

F 币
3298 元
贡献
1948 点

水王勋章元老勋章热心勋章

7#
发表于 2018-1-9 14:36:29 | 只看该作者
dypang 发表于 2018-1-9 13:48
谢谢。我问这个问题只是想了解一下fortran的更细致的规则。这两段代码,一般情况下应该是一样的。可是, ...

欲知更细的规则,请先把本站的教学视频看三遍
此外,Fortran静态方式开辟大数组在Linux下okay,在Windows下出错,往往与Fortran规则无关,与操作系统和编译原理有关
Windows下有可能是栈溢出,需要改成动态数组,也可能是32位非服务器版Windows系统的单进程2GB内存限制
希望活学活用,立竿见影,还是加群主QQ,远程桌面查找问题源头

2033

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1642 元
贡献
709 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

8#
发表于 2018-1-11 17:51:55 | 只看该作者
从语法层次,两段代码是完全一样的。
但具体编译器实现,可能就不一样了。(与操作系统的区别应该无关,而和编译器有关,只是恰好你两个操作系统使用不同的编译器而已)
(注意,类似 gfortran for windows 和 gfortran for linux,我们视为不同的编译器)

就像,“把箱子搬到楼上”和“把箱子搬到上一层”
在中文里,两者是一样的。
但具体不同的人去执行它,就可能有区别。比如A某可能用双手抱,而B某用肩膀扛。

需要更多的代码细致的调试分析,甚至不排除是编译器的bug。

7

帖子

2

主题

0

精华

入门

F 币
53 元
贡献
28 点
9#
 楼主| 发表于 2018-1-17 22:36:13 | 只看该作者
是的,大概跟编译器有关系,都是 pgfortran,但是一个是 windows 下面的版本,一个是 Linux 下面的版本。

130

帖子

10

主题

0

精华

大师

F 币
617 元
贡献
372 点

贡献勋章管理勋章帅哥勋章元老勋章星光勋章规矩勋章

10#
发表于 2018-5-2 15:27:11 | 只看该作者
你是否有確定不是 array subscript(s) out-of-bounds 的問題?
Segmentation faul:t - invalid memory reference?

在 compile-time options 若為 optimization, runtime 是不會 check 是否發生 array subscript(s) out-of-bounds
請用 non-optimization 試試
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-12-27 11:31

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表