问题
将子程序标记为elemental
时是否有任何并发症?这个页面似乎暗示了这一点,但没有详细说明它们可能是什么。
注意:我正在标记多个 fortran 版本,因为我想知道这些版本之间是否存在在开发可移植代码时应该注意的差异。
例
假设我想编写一个元素子例程来在笛卡尔坐标和极坐标之间进行转换。这可以按如下方式完成:
elemental subroutine calc_xy_from_rt( r, t, x, y )
real*8, intent(IN) :: r ! radius
real*8, intent(IN) :: t ! theta
real*8, intent(OUT) :: x
real*8, intent(OUT) :: y
x = r * cos(t)
y = r * sin(t)
end subroutine calc_xy_from_rt
因为它是元素,所以可以在以下上下文中调用它:
program main
implicit none
real*8, dimension(1:100) :: r
real*8, dimension(1:100) :: t
real*8, dimension(1:100) :: x
real*8, dimension(1:100) :: y
! (Initialize r and t arrays here)
! Calculate x and y for each element
call calc_xy_from_rt( r, t, x, y ) ! gets called 100 times
end program main
我猜这个简单的过程不会有副作用,但我提供了一个示例来使讨论具体化,并提供一个可以扩展以说明可能的副作用的 MWE。
元素子例程的明显复杂性是所有虚拟参数都必须是标量的。 有时人们希望元素操作能够访问共享数组:这不可能通过参数发生。
此外,如果一个元素子程序是纯的,它就会受到来自该性质的所有限制。
无论它是否纯,元素子程序都受到进一步的约束:
- 虚拟参数不得是指针或可分配的;
- 虚拟参数不能是共阵列;
- 虚拟参数必须是数据对象。
至于这些限制如何随时间和实施而变化,没有什么可担心的。
在Fortran 2008之前,所有元素子例程都是纯的,禁止共阵列虚拟参数是没有意义的。
此外,编译器必须能够检测到违反所述限制的情况,我不知道有任何扩展放宽了它们。
最后,然而,多年前元素过程出现时存在各种编译器错误。 人们不必太担心这些,除非拿起在大叔车库里找到的机器。