Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 使用可分配阵列的性能损失_Arrays_Fortran - Fatal编程技术网

Arrays 使用可分配阵列的性能损失

Arrays 使用可分配阵列的性能损失,arrays,fortran,Arrays,Fortran,我有一个Fortran90程序(Packmol),在以前,它是用静态内存分配实现的 我将代码更改为使用动态分配,以便在开始时分配所有数组。在一些示例中,我的性能损失为400% 然后,我验证了即使阵列的大小与使用静态分配时的大小相同,问题仍然存在。也就是说,如果我从 双精度::x(1000) 差不多 双精度,可分配::x(:) 分配(x(1000)) 这足以导致性能损失。当然,当对所有需要动态分配的数组(大约30个)执行此操作时 是否有一种方法可以更有效地分配阵列以降低性能损失?还是有人有

我有一个Fortran90程序(Packmol),在以前,它是用静态内存分配实现的

我将代码更改为使用动态分配,以便在开始时分配所有数组。在一些示例中,我的性能损失为400%

然后,我验证了即使阵列的大小与使用静态分配时的大小相同,问题仍然存在。也就是说,如果我从

双精度::x(1000)
差不多

双精度,可分配::x(:)
分配(x(1000))
这足以导致性能损失。当然,当对所有需要动态分配的数组(大约30个)执行此操作时

是否有一种方法可以更有效地分配阵列以降低性能损失?还是有人有不同的建议

多谢各位


编辑:问题不知怎么解决了。动态版本现在只比预期的静态版本稍微慢一点。我真的不知道是什么导致了之前的大减速

造成这种性能损失的原因可能有很多:

1) 静态数组总是在BSS上分配(请参阅),而“已分配”数组可以在堆或堆栈上分配。堆栈上的分配比堆上的分配快得多。一个好的编译器可以生成在堆栈上分配尽可能多的代码

2) 循环中可能有allocate/deallocate语句。每次内存分配都需要一些时间。一个好的编译器可以避免在每次分配时在物理上分配一些内存,而是重新使用已释放的空间

3) 编译器在编译时知道静态数组的维度,因此它将进行一些额外的优化

4) 如果有多维数组,则无法在编译时计算元素的地址。例如,
A(5,6,7)
的地址是
5+6*n1+7*n1*n2
,其中
n1
n2
A
的维度:
A(n1,n2,n3)
。对于静态数组,编译器可以优化此部分。此外,如果维度
n1,n2,…
是2的幂,则编译器将生成比整数乘法快3倍的位移位


数字3)是最可能的。对于编译时知道合理上限且相对较小的数组,可以保留一些静态数组(好吧,我没有放代码,因为它是一个大型程序。这里有代码:。在子例程setsizes.f90中有一个分支,其中所有数组都是动态分配的。该例程经常调用吗?在调用之间分配的大小会变吗?(或者它们是为整个程序运行而设置的。)分配本身的成本并不是很高。这取决于它的使用方式。正如你所看到的,它不太可能有人会通过这样的链接。即使现在的答案只是猜测。你应该准备一个最小的例子重现问题,找到差异大的子例程并使用它。Pro在更改为可分配数组之前和之后对代码进行归档。确保您正在测试的生成启用了适当的优化级别,并且没有启用运行时调试选项,例如数组边界检查。请注意,代码不符合要求。在这一问题得到解决之前,思考这个问题没有多大意义-这种变化可能只是由于内存损坏或类似情况导致选择了不同的执行路径。是否混淆了静态数组和自动数组?静态数组位于静态存储中。它们需要比堆栈更长的生存期(主函数堆栈除外)有。通常它们直接存在于可执行二进制文件中,尤其是在初始化时。非常感谢您的详细回答。实际上,我不会在程序中的任何时刻取消分配任何向量。所有向量都是在开始时在主程序中分配的,并且不再更改,它们通过模块共享或传递作为子例程的参数,在这些子例程中它们是用固定维度声明的。当然,编译器优化是一个问题。我认为这在我的代码中并不是那么重要。使用ifort时,使用动态内存分配时,我会得到100%的减速。我将尝试只动态分配最关键的数组。静态数组,给出n该术语的通常含义是,通常不放在堆栈上-它们通常放在数据或BSS段中。也许您考虑的是自动数组,尽管这些数组可能存储在堆栈或堆上,具体取决于实现。我不知道存储阵列数据的可分配数组的任何实现(相对于数组的描述符)在堆栈上-它们都使用堆(我只能想到非常有限的情况下,基于堆栈的可分配存储甚至是可能的)。我对一些非常具体的事情感到好奇:数组的分配顺序有什么不同?在一个语句中分配多个数组可能不同于在多个语句中分配它们?在分配向量时,有什么方法可以优化向量在内存中的位置吗?可以模拟吗静态内存分配在执行的同时所有维度都已知的情况下?@leandro我认为一次分配所有维度是(远吗?)效率更高。也应该尽早这样做。我看不出有任何方法可以使性能降低到不可修复的程度。这必须是可修复的。如果一切都做得好,我想你可能会看到最小的影响(如果有的话)。
 do i=1,10000000
    call work(a,b)
 end do

 subroutine work(a,b)
  ...
  allocate (c)
  ...
  deallocate (c)
 end
 use module_where_c_is_defined

 allocate (c)
 do i=1,10000000
    call work(a,b)
 end do
 deallocate(c)

 subroutine work(a,b)
  use module_where_c_is_defined
  if (.not.allocated(c)) then
    stop 'c is not allocated'
  endif
  ...
 end