将数组切片作为参数传递时的Fortran性能

时间:2015-03-16 22:25:25

标签: fortran slice fortran90

我喜欢fortran的数组切片符号(array(1:n)),但我想知道如果我在没有必要时使用它们,我是否会受到性能影响。

例如,考虑一下这个简单的快速排序代码(它有效,但很明显它没有注意选择一个好的支点):

recursive subroutine quicksort(array, size)

    real, dimension(:), intent(inout) :: array
    integer, intent(in) :: size
    integer :: p

    if (size > 1) then
        p = partition(array, size, 1)
        call quicksort(array(1:p-1), p-1)
        call quicksort(array(p+1:size), size-p)
    end if

end subroutine quicksort

function partition(array, size, pivotdex) result(p)

    real, dimension(:), intent(inout) :: array
    integer, intent(in) :: size, pivotdex
    real :: pivot
    integer :: i, p

    pivot = array(pivotdex)
    call swap(array(pivotdex), array(size))

    p=1
    do i=1,size-1
        if (array(i) < pivot) then
            call swap(array(i), array(p))
            p=p+1
        end if
    end do

    call swap(array(p), array(size))

end function partition

subroutine swap(a, b)

    real, intent(inout) :: a, b
    real :: temp
    temp = a
    a = b
    b = temp

end subroutine swap    

我可以轻松地传递整个数组以及递归部分应该工作的索引,但我喜欢这样的代码。然而,当我调用quicksort(array(1:p-1), p-1)时,它是否会使一个临时数组进行操作,或者它只是做一个浅的参考结构或类似的东西?这是一个足够有效的解决方案吗?

This question是相关的,但它似乎是因为跨步切片和显式大小的虚拟变量而产生临时数组,所以我对此安全,对吧?

2 个答案:

答案 0 :(得分:3)

关于效率问题:是的,对于大多数情况,使用假定形状的数组和数组切片确实是一个足够有效的解决方案。

涉及一些开销。假定形状数组需要数组描述符(有时也称为“dope vector”)。此数组描述符包含有关维度和步幅的信息,设置它需要一些工作。

带有假设形状伪参数的被调用过程中的代码必须考虑统一步幅(通常情况)和非统一步幅。某个地方的某个人可能想要使用somearray(1:100:3)的实际参数来调用你的排序例程,因为他只想对数组的每个第三个元素进行排序。不寻常,但合法。不依赖于统一步幅的代码可能会有一些性能损失。

话虽如此,编译器,尤其是那些使用链接时优化的编译器,现在在内联和/或剥离所有额外工作方面都非常好,并且还倾向于克隆特殊套管统一步骤的程序。

因此,作为一项规则,清晰度(和假设形状数组)应该获胜。请记住,在某些情况下,传递数组参数的传统方式可能会获得一些额外的效率。

答案 1 :(得分:2)

您的子阵列

  array(1:p-1)

是连续的,前提是array是连续的。

此外,您使用假定的形状数组伪参数

  real, dimension(:), intent(inout) :: array

没有必要暂时的。只传递假定形状数组的描述符。并且由于您的子阵列是连续的,即使是假定的大小,显式大小,或假定大小为contiguous属性的伪参数也可以。