【问题标题】:memcpy where size is known at compile time在编译时知道大小的 memcpy
【发布时间】:2015-06-19 11:08:20
【问题描述】:

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

调用memcpy 的函数的使用者会做类似的事情:

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

现在,我原以为 memcpy 内在函数足够聪明,可以意识到这一点:

foo<4>()

...可以用32位整数赋值替换函数中的memcpy。然而,我惊讶地发现自己这样做的速度提高了 2 倍:

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其实是一个c函数,对模板一无所知...
  • memcpy 是一个函数,因此在编译时必须知道 3 个输入中的任何一个。由于假定对齐访问且没有函数调用开销,因此使用整数赋值具有性能优势。但是,当这种假设不成立时,假设的对齐访问可能会导致 UB。
  • memcpy 是内在的。它当然不仅仅是现代 C 编译器的普通函数。尝试添加对齐信息(可能是对齐提示)。
  • 请注意,C++ 有std::copy
  • 如何编译?您是否要求您的编译器进行优化(例如,如果使用 GCC...,则使用 g++ -O2 -mtune=native -fverbose-asm -S 编译)?

标签: c++ performance memcpy


【解决方案1】:

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

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

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

如果您发现您的特殊情况获得了 2 倍的速度,并且您认为需要加快速度,那么您可以随意弄脏您的手(使用透明 cmets)。

【讨论】:

  • @ThomasKejser 对于一个调用它可能是,但如果你在另一种大小为 4 的类型上使用它,编译器应该如何为它生成另一个模板?
  • @ThomasKejser 你可以专攻alignment_of
  • @Calvin:我断言英特尔 x86_64 是否正确 - 对齐不应该成为问题?
  • x86_64 支持非对齐访问,但可能会影响性能。
  • 您是否尝试过提示编译器并查看它发出的内容?对于铿锵声,您可以使用__attribute__ ((aligned (4)))std::aligned_storage。还要去掉导致编译器丢失的void*,直接传递对象的地址。
【解决方案2】:

如果源缓冲区和目标缓冲区都作为函数参数提供:

template <size_t S>
void foo(char* dst, const char* src) {
    memcpy(dst, src, S);
}

然后clang++ 3.5.0仅在S很大时使用memcpy,但在S = 4时使用movl指令。

但是,您的源地址和目标地址不是此函数的参数,这似乎会阻止编译器进行这种激进的优化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-19
    • 2013-12-11
    • 2018-03-05
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-23
    相关资源
    最近更新 更多