Резюме:
memcpy, похоже, не может передать более 2 ГБ/сек в моей системе в реальном или тестовом приложении. Что я могу сделать, чтобы получить более быстрые копии памяти в память?
Полная информация:
Как часть приложения для захвата данных (с использованием некоторых специализированных аппаратных средств), мне нужно скопировать около 3 ГБ/сек из временных буферов в основную память. Чтобы получить данные, я предоставляю драйверу оборудования ряд буферов (по 2 МБ каждый). Аппаратные данные DMAs для каждого буфера, а затем уведомляет мою программу, когда каждый буфер заполнен. Моя программа опустошает буфер (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 С++ 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;
}
EDIT: если у вас есть дополнительные пять минут и вы хотите внести свой вклад, можете ли вы запустить вышеуказанный код на своем компьютере и опубликовать свое время в качестве комментария?