我试图通过memcpy / memset了解内存操作的性能。我测量包含memset,memcpy的循环所需的时间。请参阅附带的代码(它在C ++ 11中,但在普通C中,图片是相同的)。 memset比memcpy更快是可以理解的。但这或多或少是我理解的唯一的东西......最大的问题是:
该应用程序是单线程的! CPU是:AMD FX(tm)-4100四核处理器。
以下是一些数字:
memcpy:iters = 1 0.0625 GB in 0.1287 s:0.4857 GB /秒
memset:iters = 4 0.25 GB,0.151秒:1.656 GB /秒
memcpy:iters = 4 0.25 GB,0.1678 s:每秒1.49 GB
memset:iters = 16 1 GB,0.2406 s:每秒4.156 GB
memcpy:iters = 16 1 GB in 0.3184 s:3.14 GB /秒
memset:iters = 128 8 GB,1.074 s:7.447 GB /秒
代码:
/*
-- Compilation and run:
g++ -O3 -std=c++11 -o mem-speed mem-speed.cc && ./mem-speed
-- Output example:
*/
#include <cstdio>
#include <chrono>
#include <memory>
#include <string.h>
using namespace std;
const uint64_t _KB=1024, _MB=_KB*_KB, _GB=_KB*_KB*_KB;
std::pair<double,char> measure_memory_speed(uint64_t buf_size,int n_iters)
{
// without returning something from the buffers, the compiler will optimize memset() and memcpy() calls
char retval=0;
unique_ptr<char[]> buf1(new char[buf_size]), buf2(new char[buf_size]);
auto time_start = chrono::high_resolution_clock::now();
for( int i=0; i<n_iters; i++ )
{
memset(buf1.get(),123,buf_size);
retval += buf1[0];
}
auto t1 = chrono::duration_cast<std::chrono::nanoseconds>(chrono::high_resolution_clock::now() - time_start);
time_start = chrono::high_resolution_clock::now();
for( int i=0; i<n_iters; i++ )
{
memcpy(buf2.get(),buf1.get(),buf_size);
retval += buf2[0];
}
auto t2 = chrono::duration_cast<std::chrono::nanoseconds>(chrono::high_resolution_clock::now() - time_start);
printf("memset: iters=%d %g GB in %8.4g s : %8.4g GB per second\n",
n_iters,n_iters*buf_size/double(_GB),(double)t1.count()/1e9, n_iters*buf_size/double(_GB) / (t1.count()/1e9) );
printf("memcpy: iters=%d %g GB in %8.4g s : %8.4g GB per second\n",
n_iters,n_iters*buf_size/double(_GB),(double)t2.count()/1e9, n_iters*buf_size/double(_GB) / (t2.count()/1e9) );
printf("\n");
double avr = n_iters*buf_size/_GB * (1e9/t1.count()+1e9/t2.count()) / 2;
retval += buf1[0]+buf2[0];
return std::pair<double,char>(avr,retval);
}
int main(int argc,const char **argv)
{
uint64_t n=64;
if( argc==2 )
n = atoi(argv[1]);
for( int i=0; i<=10; i++ )
measure_memory_speed(n*_MB,1<<i);
return 0;
}
答案 0 :(得分:1)
当然这只是指令缓存加载 - 所以代码在第一次迭代后运行得更快,数据缓存加速了对memcpy / memcmp的访问以进行进一步的迭代。高速缓冲存储器位于处理器内部,因此不必经常将数据提取或放入较慢的外部存储器中 - 因此运行速度更快。