我发现自己正在调整一段代码,其中使用 memcpy 复制内存,并且在编译时已知第三个参数(大小)。

调用 memcpy 函数的使用者执行类似以下操作:

template <size_t S>
void foo() {
    void* dstMemory = whateverA
    void* srcMemory = whateverB
    memcpy(dstMemory, srcMemory, S)
}

现在,我原以为 memcpy 内在函数足够聪明,可以意识到这一点:
foo<4>()

... 可以将函数中的 memcpy 替换为 32 位整数赋值。然而,我惊讶地发现自己看到了 >2x 的加速:
template<size_t size>
inline void memcpy_fixed(void* dst, const void* src) {
    memcpy(dst, src, size);
}


template<>
inline void memcpy_fixed<4>(void* dst, const void* src) { *((uint32_t*)dst) =  *((uint32_t*)src); }

并将 foo 重写为:
 template <size_t S>
 void foo() {
    void* dstMemory = whateverA
    void* srcMemory = whateverB
    memcpy_fixed<S>(dstMemory, srcMemory)
}

两个测试都是在带有 -O3 的 clang (OS X) 上进行的。对于在编译时已知大小的情况,我真的希望 memcpy 内在函数更智能。

我的编译器标志是:
-gline-tables-only -O3 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer
我是不是对 C++ 编译器要求太多了,还是我遗漏了一些编译器标志?

最佳答案

memcpy*((uint32_t*)dst) = *((uint32_t*)src) 不同。

memcpy 可以处理未对齐的内存。

顺便说一句,大多数现代编译器确实用合适的代码发射替换了已知大小的 memcpy。对于小尺寸,它通常会发出 rep movsb 之类的东西,在大多数情况下,它可能不够快。

如果你发现你的特殊情况你获得了 2 倍的速度并且你认为你需要加速它,你可以随意弄脏你的手(有明确的评论)。

关于c++ - memcpy 在编译时已知大小,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30936642/

10-13 08:10