我试图在我的Delphi应用程序中挤压每一点性能,现在我开始使用一个与动态数组一起工作的程序 . 最慢的一行是
SetLength(结果,Len);
用于初始化动态数组 . 当我查看SetLength过程的代码时,我发现它远非最佳 . 呼叫顺序如下:
_DynArraySetLength - > DynArraySetLength
DynArraySetLength获取数组长度(初始化为零),然后使用ReallocMem,这对于启动也是不必要的 .
我一直在做SetLength来初始化动态数组 . 也许我错过了什么?有更快的方法吗?
编辑:描述主算法将占用大量空间,实际上是不必要的,因为它是车辆路径问题(http://en.wikipedia.org/wiki/Vehicle_routing_problem)的证明 . 我确实需要数以万计的分配,因为我必须保留所有数据,并将其分开保存 . Probalby如果我能想到一些聪明的数据结构会有所帮助,但我能想到的任何东西都会大大增加代码的复杂性 . 基本上我试图从低级别的东西中获得我能做的一切.1504184_m所以这是一个相当狭隘的问题:是否有可能增加这个特定的电话 . 我认为要做到这一点,我需要根据SetLength代码编写自己的初始化函数 . 并使其内联 .
6 回答
检查你如何使用你的函数:你真的需要对这个分配函数进行大量不同的调用吗?你可以像弗朗索瓦建议的那样,重新设计你的代码以减少通话次数吗?
如果你真的需要对你的函数进行一次大量的不同调用,并且需要加快速度,我认为你需要保留动态数组并使用不同的结构 .
但在此之前,并进入一个完整的调试地狱,我会强烈加入弗朗索瓦的建议,并尝试重新设计代码 .
也许您可以告诉我们更多关于您的算法的信息?它是关于处理图形3D结构?
[编辑]好的,如果它是关于解决NP完全问题,我会尽量避免分配 .
大多数情况下,您可以给出数组/堆栈/结构大小的上限 - 例如:#cities,#carsh #drivers,#roads * #cities ...
对于那些部分,我建议分配一次最大可能的数组,并手动处理你只使用前n行等的事实 .
考虑到之后可以节省的计算时间,即使在n ^ 2或n ^ 3中分配结构也是可以接受的 .
优化SetLength:你的建议是有道理的 .
但是,如果动态数组非常适合编写Delphi代码 - 主要是因为它们的语义 - 它们,恕我直言,不能很好地适应高性能计算 - 它在很大程度上依赖于RTTI,引用计数可以偶尔给你带来惊喜 . ..
你的建议是动态数组语义的变化 . 尝试查看解决方案"changing your data type"是否真的无法编写和调试 .
这是一个更多的评论,但由于在评论中发布大量代码并不漂亮,我在此处发布 .
有时,如果您不知道最终会有多少元素,那么编写这样的代码可能很诱人:
这非常糟糕,因为每次添加新元素时都需要重新分配内存 . 更好的方法(如果可能)是找到元素数量的上限,例如MAX_ELEMENTS = 100000;然后最初设置长度:
然后你创建一个变量
和写
完成填充数组后,只需截断它:
如果你只是打电话一次并且需要很长时间,那么你要求的RAM比现有的多,这会导致操作系统换出其他东西以试图为你腾出空间 . 修复:添加更多RAM,使用更小的阵列 .
如果你在一个循环中调用它,那么“realloc”就是问题所在 . 每次调用它时,逐渐增加数组的长度,Delphi重新分配整个数组,然后它将所有内容从旧数组复制到新数组 . 效率不高 .
“ Premature optimization is the root of all evil. ”
我怀疑你不得不关心一生一次的初始化......
除非你称之为无数次,否则我建议你重新设计你的代码 .
而不是多次调用包含
SetLength
的函数,而是预先分配存储,并将预分配的数组传递给函数 . 一种这样的方式是这样的:这比在内循环中调用SetLength要快得多 . 需要注意的主要是为硬件使用太多内存 .
SetLength中最慢的部分不是“无法调用”或其他东西 - 它是由内存管理器执行的内存分配(在你的情况下,ReallocMem将是简单的GetMem,因为源指针是nil) .
那么,你使用什么内存管理器?在没有FastMM的情况下,你是D7吗?
尝试安装FastMM,看看它是否有所帮助 .