概要:
在我的系统中,memcpy似乎无法在实际或测试应用程序中传输超过2GB /秒的数据。我该怎么做才能获得更快的内存到内存复制速度?
完整细节:
作为一个数据捕获应用程序的一部分(使用一些专门的硬件),我需要将大约3 GB /秒的数据从临时缓冲区复制到主内存。为了获取数据,我向硬件驱动程序提供一系列缓冲区(每个缓冲区为2MB)。硬件会将数据DMA到每个缓冲区中,然后在每个缓冲区满时通知我的程序。我的程序清空缓冲区(memcpy到另一个较大的RAM块),并将处理后的缓冲区重新提交给卡填充数据。我在使用memcpy移动数据时遇到了速度不够快的问题。看起来,在我运行的硬件上,内存到内存复制速度应该足够支持3GB /秒。Lavalys EVEREST 给出的内存复制基准测试结果为9337MB / sec,但即使在简单测试程序中,我也无法获得与此接近的速度。
我通过在缓冲区处理代码中添加/删除memcpy调用来确定了性能问题。如果没有memcpy,我可以以全数据速率运行-大约3GB / sec。启用memcpy后,我被限制在约550Mb / sec(使用当前编译器)。
为了在我的系统上对memcpy进行基准测试,我编写了一个单独的测试程序,只需在一些数据块上调用memcpy。 (我已经发布了下面的代码)我已经在我正在使用的编译器/ IDE(National Instruments CVI)以及Visual Studio 2010上运行了它。虽然我目前没有使用Visual Studio,但如果能提供必要的性能,我愿意进行切换。但是,在盲目地移动之前,我想确保它能解决我的memcpy性能问题。
Visual C++ 2010:1900 MB / sec
NI CVI 2009:550 MB / sec
虽然我并不奇怪CVI比Visual Studio慢得多,但是我对memcpy的性能这么低感到惊讶。虽然我不确定这是否可以直接比较,但这比EVEREST基准带宽低得多。虽然我不需要那么高的性能水平,但最小速度为3GB /秒是必要的。毕竟,标准库实现不能比EVEREST使用的任何东西差这么多!
在这种情况下,我该怎么做才能使memcpy更快?
硬件详细信息: AMD Magny Cours- 4x八核 128 GB DDR3 Windows Server 2003 Enterprise X64
测试程序:
#include <windows.h>
#include <stdio.h>
const size_t NUM_ELEMENTS = 2*1024 * 1024;
const size_t ITERATIONS = 10000;
int main (int argc, char *argv[])
{
LARGE_INTEGER start, stop, frequency;
QueryPerformanceFrequency(&frequency);
unsigned short * src = (unsigned short *) malloc(sizeof(unsigned short) * NUM_ELEMENTS);
unsigned short * dest = (unsigned short *) malloc(sizeof(unsigned short) * NUM_ELEMENTS);
for(int ctr = 0; ctr < NUM_ELEMENTS; ctr++)
{
src[ctr] = rand();
}
QueryPerformanceCounter(&start);
for(int iter = 0; iter < ITERATIONS; iter++)
memcpy(dest, src, NUM_ELEMENTS * sizeof(unsigned short));
QueryPerformanceCounter(&stop);
__int64 duration = stop.QuadPart - start.QuadPart;
double duration_d = (double)duration / (double) frequency.QuadPart;
double bytes_sec = (ITERATIONS * (NUM_ELEMENTS/1024/1024) * sizeof(unsigned short)) / duration_d;
printf("Duration: %.5lfs for %d iterations, %.3lfMB/sec\n", duration_d, ITERATIONS, bytes_sec);
free(src);
free(dest);
getchar();
return 0;
}
编辑:如果您有额外的五分钟时间并希望做出贡献,您可以在自己的计算机上运行上述代码,并在评论中发布您的时间。