在c++中,未使用的"new long"循环之后的所有内容都运行得更快

Everything after a loop of unused `new long` runs faster in c++

本文关键字:quot 运行 long c++ 未使用 new 循环 之后      更新时间:2023-10-16

我对此感到困惑。。此:

for (int j=0; j<100; ++j) {
long* data = new long[0];
}
clock_t launch = clock();
sim.Run();
clock_t done = clock();

运行速度比这一项快50%:

clock_t launch = clock();
sim.Run();
clock_t done = clock();

这是在使用-O3时发生的。如果我使用-O0,那么执行时间没有差异。是long还是short并不重要。向量的长度也不会改变任何东西。我没有在任何地方使用data。如果循环中的Idelete[] data;,则改进消失。当我将迭代次数减少到100以下时,性能增益减小;CCD_ 6以上没有任何区别。

如果这是Java,我会认为我正在触发GC,但这是c++!此外,它是一个单线程软件,所以它不应该是内存共享优化的东西。

这可能是什么?这种行为是我的代码中内存管理不好的症状吗?谢谢

如何说"延长50%"?我们说的是几分钟,还是几秒钟?

在几秒钟的情况下,它可能只是一个同步错误(两个clock_t可能相差两秒钟,而实时变化不超过百分之几秒)。

但我的猜测是,我们正在寻找更长的时间;在不查看代码的情况下,我怀疑通过分配"泄漏"的内存,您可以"初始化"内存堆,从而在以后更快地检索信息

这告诉我,是的,你可能对内存的管理不太优化,并且可能会从预先分配和重用内存("对象池")中受益。

对于"启动"内存堆,我的意思是,通常需要向跟踪堆内存的内存管理器分配内存;在更简单的情况下使用链表。即使您没有垃圾收集器,您仍然有一个内存管理器——它位于mallocfreerealloc等(以及new)之后。MM可以通过向操作系统请求大块,然后将其分发给应用程序,和/或通过"调整"您在请求中发出的请求来操作,这些请求可能会更好/更快地由操作系统处理。例如,操作系统通常在1K、4K或64K的中"看到"内存,具体取决于具体情况。如果您为自己分配50个10字节的字符串,它们可能会出现在不同的页面中,并浪费大量内存。MM在看到您的第一个10字节请求时,可能会分配4096个字节,然后将它们分为10字节批分发给您。

现在(我要冒险了!),假设您的应用程序需要分配相当于一整页的内存,分为十块。由于程序本身需要少量开销,因此最初的堆分配是四分之一页。

所以你继续分配你的十块。前六个适合部分空的零页;接下来的四个请求一个新页面的新分配,即第一页。

分配完成后,您开始在块之间来回处理数据,而不知道它们位于两个不同的页面中。根据操作系统、编译器、优化和天气预报,这可能意味着这些操作会产生开销

现在让我们假设您分配并泄漏了四分之三的页面。然后,当你分配第一个区块时,它不会放在第零页,第一个区块和剩下的九个区块都会放在第一页。如果-O3优化利用相同页面数据访问,您将体验到依赖编译器的性能提升。

请记住,这只是一个临时假设。在我看来,这似乎是合理的,但这并不能真正保证任何事情:-)

更多关于libc标准内存管理的详细信息(其他存在)点击这里

http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_3.html#SEC27

你也可以看看谷歌的C++工具。