【问题标题】:Performance Cost of a Memcopy in C/C++C/C++ 中 Memcpy 的性能成本
【发布时间】:2010-06-13 15:57:08
【问题描述】:

所以每当我编写代码时,我总是会考虑性能影响。我经常想知道,就性能而言,使用 memcopy 相对于其他功能的“成本”是多少?

例如,我可能正在将一系列数字写入静态缓冲区并专注于缓冲区中的帧,以便在到达缓冲区末尾时保留该帧,我可能会将其全部复制到开始或者我可以实现一个算法来分摊计算。

【问题讨论】:

  • 你有没有超越对性能的思考和衡量?
  • 我有,但不是 memcopy。
  • 始终考虑性能是编写蹩脚(而且可能很慢)代码的好方法。
  • memcpy 可以进行优化,但这涉及汇编语言、使用处理器特定功能以及针对特定情况。在考虑优化memcpy 时,首先必须问为什么首先要复制内存。首先使用智能指针和引用。
  • @Thomas:要非常小心,复制和引用都有其目的。使用引用作为优化可能非常危险(因为我发现了困难的方式......)

标签: c++ c performance


【解决方案1】:

memcpy 通常经过优化以最大化大型副本的内存带宽。当然,它没有完全避免复制那么快,而且对于固定大小的短副本,直接赋值可能会更快,因为 memcpy 有额外的代码来处理奇数长度。

但是当你需要复制一块内存时,很难击败 memcpy。它具有高度的可移植性,并且大多数编译器都竭尽全力使其速度更快,无论是使用 SIMD 指令还是内联。

【讨论】:

  • 应该避免在 C++ 中使用 memcpy,因为它是一个“愚蠢”的副本,可能会导致坏事。赋值运算符/复制构造函数绝对应该交替使用。此外,应首先运行配置文件以确定问题所在。
  • @DeadMG:许多 C++ 程序处理“哑”数据,C++ 标准将其称为“普通旧数据”,使用 memcpy 非常安全。根据我的经验,没有 POD 的程序类型最好用高级语言编写。
  • 是的。您可以使用 memcpy 并用非 POD 类型完全搞砸您的程序。或者,您可以使用赋值运算符,这最终会产生一个适用于 POD 类型的 memcpy 和一个适用于非 POD 类型的程序。
  • 赋值运算符不会导致对 POD 类型调用 memcpy。它将产生二进制图像,这与memcpy 的结果相同,没有任何优化。更好的方法是使用std::copy,它将为非 POD 类型做正确的事情,然后对其进行专门化(可能使用类型特征)以在安全的情况下调用优化的块副本,例如 memcpy
【解决方案2】:

考虑性能影响是可以的,但不要因为编写良好干净代码的真正目标而分心。如果即使您了解更多,也倾向于关注性能,请尝试关注更高级别的含义,并忽略诸如memcpy 之类的逐位内容,您可以相信编译器和库作者会对其进行优化。

通常避免过早优化这种低级类型,因为它会消耗您的时间,效果会冒泡感染整个程序,并且如果没有测量,您无法期望获得任何性能提升。

【讨论】:

    【解决方案3】:

    考虑一下 McCormick 的书“代码完成”。从那里无耻地偷东西---

    1. 算法改进通常会带来最大的性能回报。

    2. 简单的语句允许编译器有效地优化。这些具有低程序员成本。它们通常会增加可读性。无论如何,它们都是低成本的默认“应该”。

    如前所述,memcpy 已经过调整,通常对较大的内存块非常有效。那么,如果情况要求保留数据,为什么要避免它呢?

    一般不会无缘无故优化。假设您针对大量数据集编写报告。没有用户希望在这种情况下得到即时响应。他们开始工作,去吃点心。因此,如果您的代码在 10 分钟或 3 分钟内运行,则无关紧要。 给他们。他们不会注意到的。而且……他们会写你的薪水。

    程序员优化是一笔巨大的前期成本。因此,仅在需要的地方花费这笔费用。

    【讨论】:

    • 其实是史蒂夫·麦康奈尔的代码完成
    【解决方案4】:

    嗯,首先 - 只有当内存复制是您的瓶颈 时,您才应该考虑性能(而且这种情况确实很少见)。

    其次,memcpy 是使用汇编程序实现的(请参阅memcpy.asm),我猜它是可用的最快的内存复制解决方案。

    另外提一下,通常应避免 C++ 中的原始 memcpy 调用,尝试使用更抽象的包装器和例程。

    【讨论】:

    • 使用CPU寄存器可以实现简单的赋值,但是使用memcpy就不是这样了。如果分配太大,编译器无论如何都会回退到 memcpy,所以最好使用分配(如果适用...)
    【解决方案5】:

    memcpy() 将 source 中的内存内容复制到 dest。复制显然与源中元素的数量成线性关系。构成元素最佳尺寸的因素取决于机器。无论如何,根据操作的上下文,可以应用很多编译器优化黑魔法。在 C++ 中,通常更明智的做法是避免使用 memcpy 并使用赋值或复制构造函数。

    【讨论】:

    • 在现代架构上,考虑到内存架构和缓存效果,复制几乎可以肯定与元素数量不是线性关系。 memcpy 和复制构造函数正在比较苹果和橘子。
    猜你喜欢
    • 2011-05-14
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-24
    相关资源
    最近更新 更多