【发布时间】: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