为什么Fortran会花太多时间在' for_allocate'或者' for_deallocate'?

时间:2017-06-10 23:30:40

标签: optimization fortran intel-fortran

我正在尝试优化我继承的一些Fortran代码。这是一个非常重复的代码,需要几天才能运行,我正在努力减少运行时间。在减少一些函数和子程序的运行时间之后,根据VTune Amplifier,最新的瓶颈是for_deallocation和for_allocation,特别是从一个子程序调用。我有点不确定_'对于_'意味着在分配和解除分配之前,特别是在例程中没有分配。代码摘要如下:

module global_variables
    double precision, allocatable :: input_values(:)
    double precision, allocatable :: input_values2(:,:)
    double precision, allocatable :: indices_array(:)
    double precision, allocatable :: value_array(:)
    double precision, allocatable :: final_result(:)
end module

subroutine func1()
    allocate( ...global values...)
    do I=1,n
        call func2(I)
    end do

end subroutine func1

subroutine func2(I)
    double precision, intent(in) :: I
    double precision :: value, x
    double precision, dimension(3) :: output_array

    call find_Indices(x)
    value_array = input_values(indices_array)
    call calculations(value)

    do j = 1,3
        value_array = input_values2(indices_array,j)
        call calculations(output_array(j))
    end do

    final_result = output_array * value

end subroutine func2

subroutine find_Indices(position)
    indices_array = some calculation on position
end subroutine find_Indices

subroutine calculations(output)
    double precision :: output
    output = some calculation on value_array
end subroutine calculations

由于其性质,我不得不总结而不是粘贴实际代码。具有过多分配/释放时间的子例程是func2。子例程中没有分配语句,并且没有全局值的重新分配。使用我可以获得的文档,我无法确定_'对于_'在分配/解除分配之前,或者为什么在func2中花费了这么多时间。由于我指定的代码大小将所有数组放在堆上,这会占用分配,但是允许数组返回堆栈并没有减少时间。

是否有人能够帮助我了解for_allocate / for_deallocate的性质?或者这个函数花费这么多时间调用它的原因是什么?

解决方案:

在搜索数组属性时,对于我遇到的另一个问题,我遇到了这篇文章: Fortran: dynamic arrays vs. automatic array Avoiding Memory Allocation

这表明修改可分配的全局数组会产生很大的开销。将value_array从可分配数组更改为指针数组(double precicsion,pointer :: value_array(:))已经从for_allocate和for_deallocate中删除了大部分开销,并将运行时间减少到原来的1/5。这告诉我,当修改可分配数组的值时,将释放原始数组并分配新数组。这可能在Fortran社区中是众所周知的,但作为一个新用户,没有遇到任何形式的这种行为的文档,这对我来说并不明显。

1 个答案:

答案 0 :(得分:0)

查看" 6中的示例。间接阵列访问"在https://software.intel.com/en-us/articles/fortran-array-data-and-arguments-and-vectorization

重复分配(非常可能)是因为在使用索引数组时,编译器会分配一个临时数组(上面链接中的示例7.1)来存储生成的数组。另一种方法是明确循环索引(例7.2)。

上面的链接适用于MIC架构,但原理在普通CPU上可能是相同的。这里的线程https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/685221也暗示了为数组索引创建临时数组。

为了确定发生了什么,有可能检查装配输出或明确测试显式索引"场景。