Жаль, что LOR-интерпретатор не умеет распознавать такие простые ошибки, как: "капировать", "масив", "cоответсвующих" и неправильно построенного предложения.
> компилятор обязан распознать такой простой паттерн как цикл копирования
Могут быть нюансы.
Без оптимизации он ничего распознавать не будет; если копирование идет в волатильную память, то тоже ничего не будет, может, еще что -- глюки, например...
А memcpy() сейчас в большинстве компиляторов -- интринсик, даже на вызов функции времени не потратится...
На самом деле на чистом C можно сделать быстрее, чем rep movsd,
про это есть интересная (но крайне плохо написанная) книга К.Касперски.
Например, на моем P4 с размером линейки кэша в 64 байта, такая
memcpy работает быстрее всего:
#define CACHE_LINE_SIZE 16 // в int'ах
#define CACHE_LINES_IN_BATCH 4
void my_memcpy(int *dst, const int *src, int len) {
int i, j;
for (i = 0; i < len; i += CACHE_LINE_SIZE*CACHE_LINES_IN_BATCH) {
*(dst) = *(src);
*(dst+CACHE_LINE_SIZE) = *(src+CACHE_LINE_SIZE);
*(dst+CACHE_LINE_SIZE*2) = *(src+CACHE_LINE_SIZE*2);
*(dst+CACHE_LINE_SIZE*3) = *(src+CACHE_LINE_SIZE*3);
for (j = 0; j < CACHE_LINE_SIZE*CACHE_LINES_IN_BATCH/2; j++) {
*dst++ = *src++;
*dst++ = *src++;
}
}
}
gcc 4.2.1, -O2, это на 1% быстрее rep movsd и на 2-3% быстрее цикла
и memcpy(). Смысл в том, чтобы сначала загрузить 4 линейки в кэш
более-менее параллельно, и потом скопировать их без задержек. Можно
еще быстрее, нюансов при работе с памятью, как оказалось, очень много.
+ассемблер.
Но это все игрушки, на практике надо использовать обычный memcpy(),
чтобы не создавать потенциальных проблем на ровном месте, не забивать
себе голову ненужной дурью, не тратить лишнее время, а также во имя
читабельности и переносимости кода. Особенно это касается тех, кто
капирует.
> На самом деле на чистом C можно сделать быстрее, чем rep movsd,
Есть мысль, что последние версии gcc развернут сами memcpy() в оптимальноый набор команд, поскольку они не юзают либсишную memcpy(). В частности, при оптимизации под конкретное железо всегда найдется нечто быстрее rep movsd, иногда вообще без загрязнения кыша (например, bte на SGIевских Итаниумах).
Насчет копирования с префетчингом -- такой интересный опыт у меня есть.
Итаниум2, компилятор ICC, надо скопировать порядка полгига. Я делаю префетчинг (т.е. инициирую предварительную загрузку кыша -- компилятор позволял это делать), и моя функция работает в 3 раза быстрее цикла (memcpy() в той версии не был встроен).
Я доволен, и вставляю это в свою программу. Как и ожидалось, она работает гораздо быстрее, НО -- без опитмизаций. С включенной оптимизацией оно работает СУЩЕСТВЕННО медленнее, чем без префетчинга!
Вывод: компилятор сам, где надо, префетчинг правильно вставит. Если программа просто копирует данные, то, конечно, игры с кышами могут помочь. Но чуть посложнее -- увы...
>На самом деле на чистом C можно сделать быстрее, чем rep movsd
Кто программирует на ассемблере знает что rep movsd это далеко не самый быстрый способ, на С вы никогда не напишите код работающий быстрей чем ассемблерный.
>Смысл в том, чтобы сначала загрузить 4 линейки в кэш
более-менее параллельно, и потом скопировать их без задержек.
На архитектуре intel быстрей будет как раз код использующий пересылку данных минуя кэш с использованием ммх-иксной movnta