在性能方面,使用memcpy更好还是使用std::copy()更好?为什么?
char *bits = NULL;
...
bits = new (std::nothrow) char[((int *) copyMe->bits)[0]];
if (bits == NULL)
{
cout << "ERROR Not enough memory.\n";
exit(1);
}
memcpy (bits, copyMe->bits, ((int *) copyMe->bits)[0]);
理论上,memcpy可能具有微小的、难以察觉的、无限小的性能优势,只是因为它没有与std::copy相同的要求。从memcpy的手册页:
为避免溢出,请设置
由目标指向的数组
而源参数,应在
至少num字节,并且不应该
重叠(用于重叠内存
块,memmove是一个更安全的方法)。
换句话说,memcpy可以忽略数据重叠的可能性。(将重叠数组传递给memcpy是未定义的行为。)因此,memcpy不需要显式地检查这个条件,而std::copy可以使用,只要OutputIterator参数不在源范围内。注意,这并不是说源范围和目标范围不能重叠。
因此,由于std::copy有一些不同的要求,理论上它应该稍微慢一点(特别强调稍微慢一点),因为它可能会检查重叠的c数组,或者将c数组的复制委托给需要执行检查的memmove。但在实践中,您(和大多数分析人员)甚至可能察觉不到任何差异。
当然,如果不使用pod,无论如何也不能使用memcpy。
理论上,memcpy可能具有微小的、难以察觉的、无限小的性能优势,只是因为它没有与std::copy相同的要求。从memcpy的手册页:
为避免溢出,请设置
由目标指向的数组
而源参数,应在
至少num字节,并且不应该
重叠(用于重叠内存
块,memmove是一个更安全的方法)。
换句话说,memcpy可以忽略数据重叠的可能性。(将重叠数组传递给memcpy是未定义的行为。)因此,memcpy不需要显式地检查这个条件,而std::copy可以使用,只要OutputIterator参数不在源范围内。注意,这并不是说源范围和目标范围不能重叠。
因此,由于std::copy有一些不同的要求,理论上它应该稍微慢一点(特别强调稍微慢一点),因为它可能会检查重叠的c数组,或者将c数组的复制委托给需要执行检查的memmove。但在实践中,您(和大多数分析人员)甚至可能察觉不到任何差异。
当然,如果不使用pod,无论如何也不能使用memcpy。
只是一个小小的补充:memcpy()和std::copy()之间的速度差异可能会根据是否启用或禁用优化而有所不同。在g++ 6.2.0和没有优化的情况下,memcpy()明显胜出:
Benchmark Time CPU Iterations
---------------------------------------------------
bm_memcpy 17 ns 17 ns 40867738
bm_stdcopy 62 ns 62 ns 11176219
bm_stdcopy_n 72 ns 72 ns 9481749
当启用优化时(-O3),一切看起来几乎相同:
Benchmark Time CPU Iterations
---------------------------------------------------
bm_memcpy 3 ns 3 ns 274527617
bm_stdcopy 3 ns 3 ns 272663990
bm_stdcopy_n 3 ns 3 ns 274732792
数组越大,效果就越不明显,但即使在N=1000时,memcpy()在没有启用优化的情况下,速度也大约是前者的两倍。
源代码(需要谷歌基准):
#include <string.h>
#include <algorithm>
#include <vector>
#include <benchmark/benchmark.h>
constexpr int N = 10;
void bm_memcpy(benchmark::State& state)
{
std::vector<int> a(N);
std::vector<int> r(N);
while (state.KeepRunning())
{
memcpy(r.data(), a.data(), N * sizeof(int));
}
}
void bm_stdcopy(benchmark::State& state)
{
std::vector<int> a(N);
std::vector<int> r(N);
while (state.KeepRunning())
{
std::copy(a.begin(), a.end(), r.begin());
}
}
void bm_stdcopy_n(benchmark::State& state)
{
std::vector<int> a(N);
std::vector<int> r(N);
while (state.KeepRunning())
{
std::copy_n(a.begin(), N, r.begin());
}
}
BENCHMARK(bm_memcpy);
BENCHMARK(bm_stdcopy);
BENCHMARK(bm_stdcopy_n);
BENCHMARK_MAIN()
/* EOF */