memmove 的性能是 memcpy 的两倍?
Performance of memmove compared to memcpy twice?
我已经看到 What is the difference between memmove and memcpy? 中接受的答案中指出的差异,它说 memmove might be very slightly slower than memcpy
。
我们可以通过执行以下操作来实现 memmove
的替代方案:分配一个临时缓冲区,然后 memcpy
两次(src -> tmp,tmp -> dest)。我的问题是:哪种方式更快,memmove
还是替代方案?
来自http://en.cppreference.com/w/cpp/string/byte/memmove
Despite being specified "as if" a temporary buffer is used, actual implementations of this function do not incur the overhead of double copying or extra memory. For small count, it may load up and write out registers; for larger blocks, a common approach (glibc and bsd libc) is to copy bytes forwards from the beginning of the buffer if the destination starts before the source, and backwards from the end otherwise, with a fall back to std::memcpy when there is no overlap at all.
因此,开销很可能是几个条件分支。大块几乎不值得担心。
但是,值得记住的是 std::memcpy
是一个 'magic' 函数,是在两种不同类型之间进行转换的唯一合法方式。
在 c++ 中,这是非法的(未定义的行为):
union {
float a;
int b;
} u;
u.a = 10.0;
int x = u.b;
这是合法的:
float a = 10.0;
int b;
std::memcpy(std::addressof(b), std::addressof(a), size(b));
如果你是 C 程序员,你会做你期望工会做的事情。
std::memmove
"may be very slightly slower than std::memcpy
"(强调)因为它必须首先检查源和目标范围是否重叠。在内部,这只是几个指针比较;这样做之后,如果没有重叠或目标从源下方开始,它会调用 std::memcpy
;否则,它调用 std::memcpy
的变体,从末尾向开头复制。
总之,只有的区别是初步比较;完成后,就像 std::memcpy
一样。不需要额外的缓冲区和复制所有内容。
Memcpy 通常更快,因为它假定目标和源不会重叠。
因此,如果您尝试使用 memcpy 将字符串 abcd
从位置 X
复制到 X+2
,则可能会得到这样的结果
X: A B C D
memcpy 之后
X+2 A B A A
而 memmove 将保证不会丢失任何内容,因为它使用中间缓冲区来存储原始字符串。
另一方面,您可以对源和目标使用限定符 restrict
,这样您可以告诉 memmove 源和目标不重叠,这样 memmove 可以更快地选择其他算法,以防您使用此限定符。
详情见here。
我已经看到 What is the difference between memmove and memcpy? 中接受的答案中指出的差异,它说 memmove might be very slightly slower than memcpy
。
我们可以通过执行以下操作来实现 memmove
的替代方案:分配一个临时缓冲区,然后 memcpy
两次(src -> tmp,tmp -> dest)。我的问题是:哪种方式更快,memmove
还是替代方案?
来自http://en.cppreference.com/w/cpp/string/byte/memmove
Despite being specified "as if" a temporary buffer is used, actual implementations of this function do not incur the overhead of double copying or extra memory. For small count, it may load up and write out registers; for larger blocks, a common approach (glibc and bsd libc) is to copy bytes forwards from the beginning of the buffer if the destination starts before the source, and backwards from the end otherwise, with a fall back to std::memcpy when there is no overlap at all.
因此,开销很可能是几个条件分支。大块几乎不值得担心。
但是,值得记住的是 std::memcpy
是一个 'magic' 函数,是在两种不同类型之间进行转换的唯一合法方式。
在 c++ 中,这是非法的(未定义的行为):
union {
float a;
int b;
} u;
u.a = 10.0;
int x = u.b;
这是合法的:
float a = 10.0;
int b;
std::memcpy(std::addressof(b), std::addressof(a), size(b));
如果你是 C 程序员,你会做你期望工会做的事情。
std::memmove
"may be very slightly slower than std::memcpy
"(强调)因为它必须首先检查源和目标范围是否重叠。在内部,这只是几个指针比较;这样做之后,如果没有重叠或目标从源下方开始,它会调用 std::memcpy
;否则,它调用 std::memcpy
的变体,从末尾向开头复制。
总之,只有的区别是初步比较;完成后,就像 std::memcpy
一样。不需要额外的缓冲区和复制所有内容。
Memcpy 通常更快,因为它假定目标和源不会重叠。
因此,如果您尝试使用 memcpy 将字符串 abcd
从位置 X
复制到 X+2
,则可能会得到这样的结果
X: A B C D
memcpy 之后
X+2 A B A A
而 memmove 将保证不会丢失任何内容,因为它使用中间缓冲区来存储原始字符串。
另一方面,您可以对源和目标使用限定符 restrict
,这样您可以告诉 memmove 源和目标不重叠,这样 memmove 可以更快地选择其他算法,以防您使用此限定符。
详情见here。