Fortran调用:通过指针传递vs传递引用的优点

时间:2014-06-25 15:11:28

标签: pointers fortran

据我所知,Fortran数组是通过引用传递的。因此,将指针传递给大型数组(进入子程序)与传递数组本身相比,有一个优点。

您是否也可以在递归函数的上下文中澄清这一点。我已经看到了指针用于“效率”的实现,但如果所有内容都通过引用传递,那么指针的好处是什么。

这是一个例子。我有一个数组X(实际上可以说它是一个非常大的数组)。

INTEGER :: X(:)

我可以定义一个接收此数组的子路由,如下所示:

SUBROUTINE FOO(X)
    INTEGER, INTENT(IN) :: X(:)

    INTEGER :: I

    DO I = 1, 4
        WRITE(*,*) X(I)
   ENDDO
END SUBROUTINE FOO

当我调用上面的子程序时,不会复制数组X,因为fortran会传递对它的引用。现在假设我有一个子程序的修改版本:

SUBROUTINE FOO2(X)
    INTEGER, POINTER, INTENT(IN) :: X(:)
    INTEGER :: I

    DO I = 1, 4
        WRITE(*,*) X(I)
   ENDDO
END SUBROUTINE FOO2

我可以通过以下方式从程序中调用FOO2

PROGRAM TEST
IMPLICIT NONE

INTEGER, TARGET :: X(5)
INTEGER, POINTER :: Y(:)

X = (/1,2,3,4,5/)
Y => X

CALL FOO2(Y)
END PROGRAM TEST

然后这是我的问题:foo的两个版本之间是否存在性能差异?是否有任何有用的场景,FOO2的声明可能比FOO更可取?

1 个答案:

答案 0 :(得分:2)

在这个简单的情况下,不应该有任何真正的区别。请注意,该程序是非法的,您没有FOOFOO2的显式接口,但我会假设您只是为了简单而省略了它,它们位于模块或内部。

两个数组原则上可以是非连续的,所以这里没有区别。如果这会降低代码速度,contiguous属性可能会有所帮助。或假设大小或明确的大小数组。

您的子程序太简单了,因此也没有混叠的危险。这是使用指针降低性能的常见原因。可能存在与主机访问的其他参数或其他变量的潜在别名或使用关联,前提是它具有target属性。

指针参数的目的实际上是允许取消关联(null())参数,或者允许更改子例程中的关联状态。您的示例不使用,因此指针属性是多余的。

最后一点差异很小。标准中未指定在指针变量的机器代码级别实际传递给子例程的内容。如果它只是一个地址(很可能是标量),它与非指针相同,只是别名规则和允许的用法不同。否则传递一些描述符,但任何开销都应该可以忽略不计,假定的形状数组也使用描述符。