Fortran Coder

查看: 26059|回复: 28
打印 上一主题 下一主题

[讨论] 一个数组运算的问题

[复制链接]

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
跳转到指定楼层
楼主
发表于 2017-8-4 18:27:18 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
遇到一个数组片段的问题。

代码1:
do i=1,size(ia_index,2)
  ra_val(ia_index(1,i)) = ra_val(ia_index(1,i)) + ra_add(i)
  ra_val(ia_index(2,i)) = ra_val(ia_index(2,i)) + ra_add(i)
enddo

代码2:
  ra_val(ia_index(1,:)) = ra_val(ia_index(1,:)) + ra_add
  ra_val(ia_index(2,:)) = ra_val(ia_index(2,:)) + ra_add

我一直以为代码1和2得到的结果是一样的,今天遇到一个问题发现并不一样,代码1的结果是正确的,当ia_index(1,:)表示的某个下标索引出现1-2次的时候,两段代码结果一致,当出现3次的时候,代码1可以累加,代码2中ra_val索引指向的成员就只有最后一个值,没有累加。不知何故!

事实上,我最初使用代码2之前,由于不放心,是做过实验的:
[Fortran] 纯文本查看 复制代码
program main
 implicit none
   integer :: ia(5),ib(9)
   ia = [1,5,5,5,2]
   ib = 0
   ib(ia) = ib(ia) + [1,1,1,1,1]
   write(*,*) ib
   stop
 end program

结果见附件图片,无误,能够叠加我才这么写的,真是郁闷了...
还请大伙指点,先谢谢了!


aa.jpg (15.14 KB, 下载次数: 458)

aa.jpg
分享到:  微信微信
收藏收藏1 点赞点赞 点踩点踩

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
沙发
 楼主| 发表于 2017-8-5 10:21:45 | 显示全部楼层
我编了一组数据:
[Fortran] 纯文本查看 复制代码
program main
implicit none
  real :: ra_val1(11),ra_val2(11),ra_add(9)
  integer :: ia_index(2,9)
  
  integer :: i
   
  ra_add = [0.014000,0.016500,0.016500,0.014000,0.014000,0.014750,0.014750,0.010750,0.010750]
  
  ia_index(:,1) = [ 1  , 2  ]
  ia_index(:,2) = [ 1  , 9  ]
  ia_index(:,3) = [ 1  , 11 ]
  ia_index(:,4) = [ 2  , 3  ]
  ia_index(:,5) = [ 3  , 4  ]
  ia_index(:,6) = [ 4  , 8  ]
  ia_index(:,7) = [ 4  , 10 ]
  ia_index(:,8) = [ 5  , 6  ]
  ia_index(:,9) = [ 6  , 7  ]
  

  
  ra_val1 = 0.
  ra_val2 = 0.
  
  ! 写法1
  do i=1,9
    ra_val1(ia_index(1,i)) = ra_val1(ia_index(1,i)) + ra_add(i)
    ra_val1(ia_index(2,i)) = ra_val1(ia_index(2,i)) + ra_add(i)
  enddo
  
  ! 写法2
  ra_val2(ia_index(1,:)) = ra_val2(ia_index(1,:)) + ra_add
  ra_val2(ia_index(2,:)) = ra_val2(ia_index(2,:)) + ra_add
  
  
  write(*,"(A6,2A12)") "No.","Val1","Val2"
  do i=1,11
    write(*,"(I6,2F12.6)") i,ra_val1(i),ra_val2(i)
  enddo
  
  stop
end program

aa.jpg (29.29 KB, 下载次数: 430)

aa.jpg

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
板凳
 楼主| 发表于 2017-8-5 10:23:01 | 显示全部楼层
本帖最后由 andy8496 于 2017-8-5 10:27 编辑
fcode 发表于 2017-8-5 04:48
It's hard to check why ? May be we need more code !

上面的代码为什么写法1和2结果不同?理解不了,我认为结果应该是一样的,都是写法1的结果。还请老大赐教!

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
地板
 楼主| 发表于 2017-8-5 21:29:22 | 显示全部楼层
唉,我都忘了我哪些地方用了这种写法,但是肯定不止目前发现的这个位置。真是郁闷了!
要是能通过什么编译选项能设置解决就好了!
谢了!

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
5#
 楼主| 发表于 2017-8-6 18:30:55 | 显示全部楼层
pasuka 发表于 2017-8-6 17:22
ia_index的第1行数据为啥非要设置重复元素?

这个是实际应用的需要。

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
6#
 楼主| 发表于 2017-8-6 21:40:23 | 显示全部楼层
本帖最后由 andy8496 于 2017-8-6 21:41 编辑
pasuka 发表于 2017-8-6 21:28
症结即在于此呀,没有看出来?

真看不出来。我试验用的那段代码,咋就能按照我的理解运行呢?索引数组也是有重复元素的:
program main
implicit none
   integer :: ia(5),ib(9)
   ia = [1,5,5,5,2]
   ib = 0
   ib(ia) = ib(ia) + [1,1,1,1,1]
   write(*,*) ib
   stop
end program

aaa.jpg (15.14 KB, 下载次数: 237)

aaa.jpg

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
7#
 楼主| 发表于 2017-8-7 09:15:14 | 显示全部楼层
好吧,总算看到一点依据了。虽然心中不服,比如:五楼的大哥的方法为什么又可行?
还有两点疑问,还要继续麻烦大家指点:
chiangtp附件中提到的,
①a many-one array section must NOT Assign To NOR Read In Compiler may not Check at Runtime owing to the Performance Cost
VS+IVF中,Debug中如何打开这个检查?
②the use of vector subscripting is very inefficient and should not be used unless absolutely necessary (although easy to coding)
这句话该如何理解?数据片段只是写起来方便,但是运行效率低?

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
8#
 楼主| 发表于 2017-8-7 14:52:45 | 显示全部楼层
多谢各位了!
现在补救的办法就是依赖编译器检查了,不知道可行否?在哪里设置?


2. whole array的assignment(多個要做的規則), 定義上是in-any-order+parallel(如果能), runtime時 "五楼的大哥的方法", "Debug打开检查" 都是compiler/compile-time-options/... dependent

这个设置我没找到在哪儿……

setting.jpg (75.14 KB, 下载次数: 220)

setting.jpg

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
9#
 楼主| 发表于 2017-8-7 15:55:07 | 显示全部楼层
惭愧!惭愧!
已经是心服口服了!
目前遇到的困难是:工程已经相当大,目前不知道那些位置有这个问题;现在想改……

123

帖子

32

主题

0

精华

宗师

F 币
1562 元
贡献
795 点
10#
 楼主| 发表于 2017-8-10 21:25:38 | 显示全部楼层
本帖最后由 andy8496 于 2017-8-10 21:27 编辑

当时就是想以最少的代码实现一个累加,也略微表示怀疑,但是试验后来发现成功了,就采用了,但后来才发现了这样一个大bug。
等号左边的数组片段中,表示下表的数组不能有重复元素。后来在各位的帮助下找到依据了,如15楼pasuka的资料就非常详细。

当时做这样的语法规定,个人理解是为了防止在数组初始化的时候,某个重复下表指向的成员得到了不确定的值,因为数组片段可能采用了并行的方法来赋值(纯猜测),这样就不知道最终这些重复下标的成员最终得到的是何值。
个人认为:
①在单纯的数组赋值时,编译器对于这种错误程序运行时应该报错,而不应该任由错误发生。如:
b( (/ 1, 7, 3, 7 /) ) = (/ 1, 2, 3, 4 /) ! 运行时应该有报错提示
②对于累加的需求,应该从语法层面予以支持,如:
b( (/ 1, 7, 3, 7 /) ) =b( (/ 1, 7, 3, 7 /) ) +1 !等号左右有相同的数组片段应该实现循环相同的效果。

最后,再次感谢各位的热心帮助!
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

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

GMT+8, 2024-5-5 10:05

Powered by Tencent X3.4

© 2013-2024 Tencent

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