回 帖 发 新 帖 刷新版面

主题:[讨论]矢量下标作数组索引时的只读属性

最近在 debug 程序时得到了确认,花去了我几天的时间,实在有些不甘心。为避免诸位误入此类陷阱,特发帖说明。其实无论是 Intel 的 reference 还是 IBM 的线上文档都有说明,但在遇到这个问题之前谁又会注意到呢?:P

    program main
        implicit none
        integer, dimension(4) :: array

        array = 0
        call eval(array(2:), 3)
        print *, array(3)

        array = 0
        call eval(array((/2,3,4/)), 3)
        print *, array(3)

        stop
    end program

    subroutine eval(a, n)
        implicit none
        integer, intent(in) :: n
        integer, dimension(n) :: a

        a(2) = -1

        return
    end subroutine eval

以上为测试代码,如果遇到过这个问题的朋友,一看便知。

[quote][I]If you pass an array section with a vector subscript as an actual argument, the associated dummy argument must not be defined or redefined.[/I][/quote]
这是 IBM 线上文档对于矢量下标哑实传递的说明。用的是 must not be defined or redefined,所以我想这应该是个只读属性。正如上例中所示,即使 redefined,实参并无影响。

但如果不作子程序传递,直接赋值,比如:

array((/2,3,4/)) = -1

这是可行的。也即,只是哑实传递时才会有这个限制。对于 Intel 汇编不熟悉,不太清楚编译器是如何实现的。是直接抛弃还是在传递时作了复制操作?


另外,基于 gcc 4.5.3 的 gfortran 尚不支持 array((/1,3:4/)) 这种混合下标索引。

回复列表 (共17个回复)

沙发

果然是有这种问题. 在linux下测试了ivf11.1, 12 和gfortran 4.5.2. 第二次调用所修改的值没有传递回去原数组.
如果它等同于只读属性而进行了修改, 编译器不提示, 这实在有风险.
等有时间查查相关的文档.

多谢楼主辛苦提示!!

板凳

第二次调用时,程序将数组做了一个副本,所以会有这样的现象出来:)
试想,如果不做副本,你的下标不连续我该在子程序中如何访问?

3 楼

恩,这是非地址传递的一种情况

4 楼

@yeg001:
是哦,编译器应该有个 warning,比如子例程中没有加 intent(in) 属性时。

@cgl_lgs:
嗯,这个反问很有道理。应该是作了复制操作。但如果有人帮忙看下汇编,会更加放心些。:)


有人考虑去给 gfortran 提交个补丁么?顺便把混合下标也一并支持了吧。XD

5 楼

objdump -d自己看下就知道了

补丁这个要看是不是现有路线图中的,估计改array.c那几个match就行了
个人感觉这个用法很少见,而且是很低效的写法(指运行效率)

6 楼

@dongyuanxun:
之前看过 arm assembly,但 intel 语法好像复杂些。不想去学习嘛。:P
你看过后确认是有副本操作了吗?
效率能低多少,方便倒是,我自己常用。我的实际情况是要求解矩阵部分行列的逆阵,有什么更理想的算法么?

7 楼

你看下汇编就知道了,第一次使用只有6条指令左右,第二次有20多条,大多数都是赋值操作,肯定效率低了。

我觉得你可以在传递之前先重新构造一个数组再传递即可,用循环之类的均可,因为现在编译器自动向量化水平都还可以,这种级别的循环很容易转变成SIMD指令。

8 楼

如果对于小数组(矩阵)这样倒不是不行,但确实应少用这样的方式,用连续的行或列完全可以不用这样的表达方式:)

9 楼

这种用法可能不会用得很多,不过就语义来说,既然不返回修改值,那还是应该提示一下.
继续关注中.

10 楼

@dongyuanxun @cgl_lgs:
按照我首帖的说明,我的这种求逆需求显然需要重构数组的。连续的行列只用到 subscript triplets 索引即可,也不必重构。矢量下标索引在我需要抽取数组片断时还是很方便。:D

我来回复

您尚未登录,请登录后再回复。点此登录或注册