【问题标题】:memcpy performance vs byte shiftmemcpy 性能与字节移位
【发布时间】:2015-07-28 08:40:57
【问题描述】:

有2个变量:

uint32_t var32 = 0xAABBCCDD;
uint8_t var8[4] = { 0, 0, 0, 0 };

var32 到 var8 的哪种复制方式会更快?

for (size_t i = 0; i < sizeof(uint32_t); i++)
    var8[i] = (uint8_t)(var32 >> (i * 8));

memcpy(var8, &var32, sizeof(uint32_t));

感谢所有提示。

【问题讨论】:

    标签: c memory-management memcpy


    【解决方案1】:

    假设是 32 位架构,memcpy 归结为单个 mov(或类似)指令。所以它更快。但这也是错误的。从 C 的角度来看,您正在调用 实现定义 行为来执行此操作。现实中可能发生的情况是您的字节顺序错误,这取决于您是在 big endian 还是 little endian 平台上。因此,只需使用位移位解决方案,而不必担心性能。

    【讨论】:

    • 如果您知道执行代码的机器的字节序,memcpy 将按预期工作。从 C 标准的角度来看,它仍然是未定义的行为。您应该在您确定代码是真正性能瓶颈的情况下考虑此类依赖于平台的优化。
    • @EOF 你是对的,它适用于字节。结果仍然未定义。正在考虑如何改写我的答案以使其清楚。
    • @ŁukaszPrzeniosło 哦,那就改用 htole32
    • @Vality 这是一个很好的答案,但鉴于当今大多数 平台都是little endian,它不会优化任何东西。如果不是绝对必要,我的观点是不要尝试这种优化。
    • @FelixPalmen:嗯,字节顺序不是undefined,它是implementation-defined,所以结果也不是undefined。跨度>
    【解决方案2】:

    现代编译器通常保证 C 中的 memcpy 可以优化为可用的最快复制方式。但是,这确实假定它已在您的实现中正确内联。

    我也不相信这会导致严格的别名违规,因为这两个指针永远不会对同一内存进行别名。

    但是,将 int 的字节复制到数组的哪个字节中的顺序是实现定义的。如果您希望确保它始终采用大端顺序,您可以首先在 int 上运行htonl,这将使其成为大端,然后复制的结果将得到很好的定义。在不需要的情况下,这也将优化到零,使其始终是任何系统上最快的实现。

    另一方面,如果您想要小端字节序,请使用htole32 以确保 int 在任何硬件上都变为小端字节序。但是请注意,htole32 是 BSD、Linux 和各种其他操作系统中的扩展,并且不能保证在所有实现中都可用(读取,非标准)。

    【讨论】:

    • +1 以“安全”的方式优化它。但仍需注意 htole32 未包含在 C 标准中。
    • @FelixPalmen 在第二部分为真,我将在答案中添加警告。谢谢。
    • 严格别名不适用于memcpy/memmove,因为复制字节(又名通过char*)。但是对于memcpydstsrc 不能重叠。
    【解决方案3】:

    我认为 memcpy 会更快,因为它不计算只使用移动。字节移位有两步计算。

    【讨论】:

    • 这没有帮助。看我的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多