Резюме:
memcpy, по-видимому, не может передавать более 2 ГБ / с в моей системе в реальном или тестовом приложении. Что я могу сделать, чтобы получить более быстрые копии из памяти в память?
Полная информация:
Как часть приложения для сбора данных (с использованием некоторого специализированного оборудования) мне нужно скопировать около 3 ГБ / с из временных буферов в основную память. Для сбора данных я предоставляю драйверу оборудования серию буферов (по 2 МБ каждый). Аппаратные DMA передают данные в каждый буфер, а затем уведомляют мою программу о заполнении каждого буфера. Моя программа очищает буфер (memcpy в другой, больший блок оперативной памяти) и повторно помещает обработанный буфер в карту для повторного заполнения. У меня проблемы с memcpy, перемещая данные достаточно быстро. Кажется, что копирование из памяти в память должно быть достаточно быстрым, чтобы поддерживать 3 ГБ / с на оборудовании, на котором я работаю. Lavalys EVEREST дает мне результат теста производительности копирования памяти 9337 МБ / с, но я не могу приблизиться к этим скоростям с помощью memcpy, даже в простой тестовой программе.
Я выделил проблему производительности, добавив / удалив вызов memcpy внутри кода обработки буфера. Без memcpy я могу работать с полной скоростью передачи данных - около 3 ГБ / с. С включенной memcpy я ограничен до 550 Мб / с (используя текущий компилятор).
Чтобы протестировать memcpy в моей системе, я написал отдельную тестовую программу, которая просто вызывает memcpy для некоторых блоков данных. (Я разместил код ниже). Я запустил его как в компиляторе / IDE, который я использую (National Instruments CVI), так и в Visual Studio 2010. Хотя в настоящее время я не использую Visual Studio, я готов сделать переключатель, если он даст необходимую производительность. Однако, прежде чем вслепую перейти, я хотел убедиться, что это решит мои проблемы с производительностью memcpy.
Visual C ++ 2010: 1900 МБ / с
NI CVI 2009: 550 МБ / с
Хотя я не удивлен, что CVI значительно медленнее, чем Visual Studio, я удивлен, что производительность memcpy такая низкая. Хотя я не уверен, что это прямо сопоставимо, это намного ниже, чем пропускная способность EVEREST. Хотя мне не нужен такой уровень производительности, требуется минимум 3 ГБ / с. Конечно, реализация стандартной библиотеки не может быть намного хуже, чем то, что использует EVEREST!
Что, если что, я могу сделать, чтобы memcpy быстрее работал в этой ситуации?
Детали оборудования:
AMD Magny Cours - восьмеричное ядро 4x
128 ГБ 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;
}
РЕДАКТИРОВАТЬ: Если у вас есть дополнительные пять минут и вы хотите внести свой вклад, вы можете запустить приведенный выше код на своем компьютере и опубликовать свое время в качестве комментария?