【问题标题】:Cost of memory [de]allocation and potential compiler optimizations (c++)内存 [de] 分配成本和潜在的编译器优化 (c++)
【发布时间】:2011-08-03 07:23:22
【问题描述】:

是否明确定义了内存 [de] 分配的成本?如果成本取决于所使用的特定编译器,是否有一种实现内存 [de] 分配的通用方式,以便我可以合理地承担成本?

编译器是否能够优化以下代码,使得对“new”的调用只执行一次?

char * arr = NULL;
for (size_t i = 0; i < 5000000000; ++i)
{
    arr = new char[100000000]
    ... // Process things here
    delete []arr;
}

【问题讨论】:

  • 嗯...首先,哪个编译器?
  • 在我看来就像一个无限循环。

标签: c++ memory-management compiler-optimization overhead


【解决方案1】:

编译器几乎可以肯定无法执行此优化。在最低级别,存储分配归结为对库函数的调用,例如malloc(以及更深一层的操作系统 API)。对于编译器来说,假设可以忽略单个 malloc/free 对并重用它们的存储是不安全的,因为它们的实现应该在优化器的范围之外。

除此之外,我认为这对优化器来说不是一件好事。这是你,程序员,不需要特别努力就可以做到的事情。

内存分配/释放没有标准化的成本。通常,分配/解除分配时间可能会有很大差异(例如,如果强制用户空间堆实现从 OS 内核的内存管理器获取新页面,则需要更长的时间)。

一个合理的经验法则是,小分配很可能比大分配快,分配应该比取消分配慢。

【讨论】:

  • 这个循环可能表现出很好的性能,这取决于 malloc 的实现方式。这个未使用的块可能只是坐在它的下一个空闲指针中,因此 new 根本没有工作。
  • C 标准(以及扩展的 C++)将 mallocfree 定义为实现的一部分。编译器被赋予了假设语义的一切权利。 C++ 更进一步明确地批准替换newdelete(但不是mallocfree),并指定了对此的要求。同样,编译器可能会假设 newdelete 满足他们的要求。
  • 这很有趣...为什么释放比分配慢?
  • @MSalters 我不明白你的评论。您是说 newdelete 的实现是由 C++ 标准定义的?如果标准是硬件无知的(并且它们的实现需要硬件知识),如何定义它们?还是这个假设不正确?
【解决方案2】:

编译器可能有一些设置来优化你的代码片段(有一些错误),但你必须告诉编译器你是在优化速度还是优化大小。标准中没有说明所需的性能程度。

我会考虑分配和释放,因为我不想依赖编译器。

此外,由于标准 C++ 语言中没有垃圾收集,因此您的分配和释放可能会对碎片化内存造成严重破坏(或减慢执行速度)。

顺便说一句,您的错误是将变量“i”(一个整数)与浮点数“5000000000.0”进行比较。注意小数点。良好的编程习惯是将整数与整数进行比较,将浮点数与浮点数进行比较。

【讨论】:

  • 好的做法是将 signed 整数与 signed 整数等进行比较...;)
  • @rubenvb:抱歉,今天我的迂腐认知度很低。
【解决方案3】:

分配 char[100000000] 的时间与将所有元素设置为 0 的时间相比要小得多(无论如何构造函数都应该这样做)。而且,如果您的代码写入每个单元格,分配比其他任何东西都便宜得多。

而且我认为没有编译器可以使它工作并且只调用构造函数。

【讨论】:

  • -1,编译器不应将内存归零。 char 没有演员。
  • 不知道,但是,操作每个单元格比分配要昂贵得多。
  • 确实如此,但通常不会发生(调试版本除外,然后内存通常设置为非零调试模式)。
猜你喜欢
  • 1970-01-01
  • 2018-04-10
  • 2018-12-30
  • 1970-01-01
  • 1970-01-01
  • 2015-08-31
  • 1970-01-01
  • 2014-02-21
相关资源
最近更新 更多