LINUX.ORG.RU

memcpy работает с такой же скоростью или быстрее, но писать меньше, поэтому используй его.

anonymous
()

компилятор обязан распознать такой простой паттерн как цикл копирования -- так что не заморачивайся и пиши цикл.

dilmah ★★★★★
()

Жаль, что LOR-интерпретатор не умеет распознавать такие простые ошибки, как: "капировать", "масив", "cоответсвующих" и неправильно построенного предложения.

parser ★★
()
Ответ на: комментарий от dilmah

> компилятор обязан распознать такой простой паттерн как цикл копирования

Могут быть нюансы.

Без оптимизации он ничего распознавать не будет; если копирование идет в волатильную память, то тоже ничего не будет, может, еще что -- глюки, например...

А memcpy() сейчас в большинстве компиляторов -- интринсик, даже на вызов функции времени не потратится...

Die-Hard ★★★★★
()

На самом деле на чистом 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(),
чтобы не создавать потенциальных проблем на ровном месте, не забивать
себе голову ненужной дурью, не тратить лишнее время, а также во имя
читабельности и переносимости кода. Особенно это касается тех, кто
капирует.

AMDmi3
()
Ответ на: комментарий от AMDmi3

> На самом деле на чистом C можно сделать быстрее, чем rep movsd,

Есть мысль, что последние версии gcc развернут сами memcpy() в оптимальноый набор команд, поскольку они не юзают либсишную memcpy(). В частности, при оптимизации под конкретное железо всегда найдется нечто быстрее rep movsd, иногда вообще без загрязнения кыша (например, bte на SGIевских Итаниумах).

Насчет копирования с префетчингом -- такой интересный опыт у меня есть.

Итаниум2, компилятор ICC, надо скопировать порядка полгига. Я делаю префетчинг (т.е. инициирую предварительную загрузку кыша -- компилятор позволял это делать), и моя функция работает в 3 раза быстрее цикла (memcpy() в той версии не был встроен).

Я доволен, и вставляю это в свою программу. Как и ожидалось, она работает гораздо быстрее, НО -- без опитмизаций. С включенной оптимизацией оно работает СУЩЕСТВЕННО медленнее, чем без префетчинга!

Вывод: компилятор сам, где надо, префетчинг правильно вставит. Если программа просто копирует данные, то, конечно, игры с кышами могут помочь. Но чуть посложнее -- увы...

Die-Hard ★★★★★
()
Ответ на: комментарий от AMDmi3

>На самом деле на чистом C можно сделать быстрее, чем rep movsd

Кто программирует на ассемблере знает что rep movsd это далеко не самый быстрый способ, на С вы никогда не напишите код работающий быстрей чем ассемблерный.

>Смысл в том, чтобы сначала загрузить 4 линейки в кэш
более-менее параллельно, и потом скопировать их без задержек.

На архитектуре intel быстрей будет как раз код использующий пересылку данных минуя кэш с использованием ммх-иксной movnta

anonymous
()
Ответ на: комментарий от AMDmi3

От проца зависит. На п4 movs быстрее, на п1 - через фпу, на п2/3 - через simd

madcore ★★★★★
()
Ответ на: комментарий от Die-Hard

> Вывод: компилятор сам, где надо, префетчинг правильно вставит

Тем не менее, на всех моих gcc (4.2.1, 4.2.4, 4.3.1) memcpy() на O2 оказывается медленнее даже тупого while(count--) *dst++ = *src++;

AMDmi3
()
Ответ на: комментарий от AMDmi3

> ...на всех моих gcc (4.2.1, 4.2.4, 4.3.1) memcpy() на O2 оказывается медленнее...

Ну да, я тоже такое часто наблюдал...

Тем не менее, в "толстых" программах "в среднем" memcpy(), вроде, выигрывает.

Я не утверждаю наверняка -- я пару раз сам тестировал, и мое решение (для себя) -- юзать memcpy().

Die-Hard ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.