Мне нужна помощь в выполнении следующего кода. Он выполняет memcpy на двух динамически распределенных массивах произвольного размера:
int main()
{
double *a, *b;
unsigned n = 10000000, i;
a = malloc(n*sizeof(double));
b = malloc(n*sizeof(double));
for(i=0; i<n; i++) {
a[i] = 1.0;
/* b[i] = 0.0; */
}
tic();
bzero(b, n*sizeof(double));
toc("bzero1");
tic();
bzero(b, n*sizeof(double));
toc("bzero2");
tic();
memcpy(b, a, n*sizeof(double));
toc("memcpy");
}
tic/toc измеряет время выполнения.
На моем компьютере он занимает 0.035s для memcpy (Linux, gcc версии 4.4.6). Если я сейчас раскомментирую строку, которая инициализирует целевой массив b, код будет в три раза быстрее (!) - 0.011 с.
Я наблюдал подобное поведение при использовании цикла вместо memcpy. Обычно меня это не волнует, так как достаточно "инициализировать" память перед ее использованием. Однако теперь мне нужно выполнить простую копию памяти и сделать это как можно быстрее. Для инициализации данных требуется запись, например. 0 в память, что не является необходимым и требует времени. И я хотел бы выполнить копию памяти со всей доступной пропускной способностью памяти.
Есть ли решение этой проблемы? Или это связано с тем, как Linux обрабатывает динамическую память (какое-то ленивое распределение страниц?) И не может быть сработано? Как это делается на других системах?
Изменить: Те же результаты получены с помощью gcc 4.6. Я использовал -O3 для компиляции.
Edit: Спасибо всем за ваши комментарии. Я понимаю, что отображение памяти требует времени. Наверное, мне просто трудно принять, что это занимает так много времени, намного дольше, чем фактический доступ к памяти. Код был изменен, чтобы включить контрольную отметку инициализации массива b, используя два последующих вызова bzero. На экране теперь отображаются
bzero1 0.273981
bzero2 0.056803
memcpy 0.117934
Очевидно, что первый вызов bzero much больше, чем просто нулевые потоки в памяти - это сопоставление памяти и обнуление памяти. Второй вызов bzero, с другой стороны, занимает половину времени, необходимого для выполнения memcpy, что точно так же, как ожидалось, - записывать только время против времени чтения и записи. Я понимаю, что накладные расходы второго вызова bzero должны быть там из-за соображений безопасности ОС. А как насчет остальных? Могу ли я каким-то образом уменьшить его? использовать большие страницы памяти? Различные настройки ядра?
Я должен упомянуть, что я запускаю это на свистке Ubuntu.