gpt4 book ai didi

arrays - 使用可分配数组的性能损失

转载 作者:行者123 更新时间:2023-12-02 06:39:02 24 4
gpt4 key购买 nike

我有一个 Fortran90 程序 (Packmol),直到它是通过静态内存分配实现的。

我更改了代码以使用动态分配,这样所有数组都在开始时分配。在某些示例中,我的性能损失了 400%。

然后,我验证了即使数组的大小与我使用静态分配时的大小相同,问题仍然存在。也就是说,如果我更改分配
<code>double precision :: x(1000)</code>
类似的东西
<code>double precision, allocatable :: x(:)</code>
<code>allocate(x(1000))</code>
这足以导致性能损失。当然,当所有需要动态分配的数组都这样做时,大约有30个。

有没有一种方法可以更有效地分配数组以减少性能损失?或者有人有不同的建议吗?

非常感谢。

编辑:不知何故,问题得到了解决。动态版本现在仅比静态版本稍慢,这是预期的。我真的不知道是什么导致了之前的大幅放缓。

最佳答案

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

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

2) 您可能在循环中有分配/解除分配语句。每次内存分配都会花费​​一些时间。一个好的编译器可以避免在每次分配时物理地分配一些内存,而是重新使用已释放的空间。

3)编译器在编译时就知道静态数组的维度,因此它会做一些额外的优化。

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

数字 3) 是最有可能的。您可以为在编译时知道合理上限的数组保留一些静态数组,这些数组相对较小(大约<1000个元素),并且也在经常调用且执行少量工作的例程内.

根据经验,只有小型数组可以静态分配:大多数 1D 数组、一些小型 2D 数组和微小的 3D 数组。将所有其余的转换为动态分配,因为它们可能无法放入堆栈中。

如果您有一些频繁的分配/解除分配,因为您在循环中调用子例程,如下所示:

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

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

如果c 始终具有相同的维度,您可以将其作为子例程的参数,或者作为在调用工作之前仅分配一个的全局变量:

 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

关于arrays - 使用可分配数组的性能损失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35901756/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com