Fortran performance when passing array slices as arguments

点点圈 提交于 2019-12-11 04:35:06

问题


I like fortran's array-slicing notation (array(1:n)), but I wonder whether I take a performance hit if I use them when it's not necessary.

Consider, for example, this simple quicksort code (It works, but obviously it's not taking care to pick a good pivot):

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    

I could just as easily pass the whole array along with the indices of where the recursive parts should be working, but I like the code this way. When I call quicksort(array(1:p-1), p-1), however, does it make a temporary array to operate on, or does it just make a shallow reference structure or something like that? Is this a sufficiently efficient solution?

This question is related, but it seems like it makes temporary arrays because of the strided slice and explicit-sized dummy variables, so I'm safe from that, right?


回答1:


Your subarray

  array(1:p-1)

is contiguous, provided array is contiguous.

Also, you use an assumed shape array dummy argument

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

There is no need for a temporary. Just the descriptor of an assumed shape array is passed. And as your subarray is contiguous, even an assumed size, or explicit size, or assumed size dummy argument with the contiguous attribute would be OK.




回答2:


Regarding your question of efficiency: Yes, for most cases, using assumed-shape arrays and array slices is indeed a sufficiently efficient solution.

There is some overhead involved. Assumed-shape arrays require an array descriptor (sometimes also called "dope vector"). This array descriptor contains information about dimensions and strides, and setting it up requires some work.

The code in the called procedure with an assume-shape dummy argument has to take both unity stride (the usual case) and non-unity stride into account. Somebody, somewhere, might want to call your sorting routine with an actual argument of somearray(1:100:3) because he only wants to sort every third element of the array. Unusual, but legal. Code that cannot depend on unity stride may have some performance penalty.

Having said that, compilers, especially those using link-time optimization, are quite good nowadays in inlining and/or stripping away all the extra work, and also tend to clone procedures for special-casing unity strides.

So, as a rule, clarity (and assumed-shape arrays) should win. Just keep in mind that the old-fashioned way of passing array arguments may, in some circumstances, gain some extra efficiency.



来源:https://stackoverflow.com/questions/29088071/fortran-performance-when-passing-array-slices-as-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!