2017-06-10 57 views
1

我想优化一些我已经继承的Fortran代码。这是一个非常重复的代码,需要数天才能运行,我正在努力减少运行时间。根据VTune放大器的说法,减少了一些函数和子程序的运行时间后,最新的瓶颈就是for_deallocation和for_allocation,特别是从一个子例程中调用。我稍微不确定'for_'在分配和释放前的含义,尤其是在例程中没有分配。代码摘要如下:为什么Fortran在'for_allocate'或'for_deallocate'上花费这么多时间?

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。子程序中没有分配语句,并且没有重新分配全局值。使用我可用的文档,我一直无法确定在分配/释放之前'for_'是什么意思,或者为什么在func2中花费了很多时间。由于我指定的代码的大小将所有数组放在堆上,这会占用一个分配,但是允许数组返回堆栈并没有减少时间。

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

SOLUTION:

虽然谷歌搜索阵列性能,我有另外一个问题,我碰到此帖一: Fortran: dynamic arrays vs. automatic array Avoiding Memory Allocation

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

+0

我们需要一些上下文。一个可编译的子程序,至少(最好是一个小程序)和你正在使用的编译器。 – Jack

+1

在没有更好的信息的情况下,人们可能会猜测你需要内联或者这样的优化来保持动态数组跨多次调用func2,以及可能尝试堆栈和堆。 output_array似乎最有可能通过昂贵的分配转移到堆上。 for_只是指Fortran运行时库。 – tim18

+0

我正在使用intel 17.0编译器。我会看看我能做些什么来创建一个可编辑的例子。 我应该意识到'for_'会代表Fortran,我只是觉得英特尔使用'fort'作为Fortran的缩写。 –

回答

0

结帐在https://software.intel.com/en-us/articles/fortran-array-data-and-arguments-and-vectorization

在“6.间接阵列访问”实施例中的重复分配是(很可能)因为使用索引数组时,编译器(在链路上面的例子7.1)分配一个临时数组存储结果数组。另一种方法是在索引上明确循环(例7.2)。

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

为了确定发生了什么,可以检查组件输出或明确测试“显式索引”场景。

相关问题