Pull to refresh

Comments 36

Интересно, еще хотелось бы узнать и про не-x86 реализации.
Сорри, у меня в лабе куча всего, но по понятным причинам только Интел. Даже померять не начем. Может быть, кто-нибудь прокомментирует про ARM, MIPS, SPARC или POWER?
UFO just landed and posted this here
мои тесты не пойдут, у меня все на x86 assembly. Впрочем, на POWER, возможно и проблемы зоопарка memcpy нет — все таки RISC, все там должно быть аккуратненько.
На sandy bridge сегодня могу протестировать.

у копирования через non temporal ограниченная применимость. Там, где применимо, оно, конечно, должно быть быстрее rep movs
На архитектурах с явным параллелизмом команд используется SWP-версия memcpy, разанроленная на несколько итераций. Но если надо скопировать всего несколько байт, то быстрее будет обычная load/store реализация.
В добавок, для больших массивов, надо использовать префетч данных в кеши разных уровней.
С учётом этого, проверок на выровненность и т.п., memcpy разростается до нескольких сотен строк :)
А что, там не простого h/w stride prefetcher'а?
В Итаниуме вообще нет h/w prefetcher'а, в Эльбрусе не знаю :)
На мой взгляд, так и должно было быть всегда. Меня всегда удивляло, почему movsb не эффективен и программисты создают свои длинные и сложные функции копирования. Ведь раз есть процессорные инструкции, специально предназначенные для копирования памяти, то именно они и должны копировать память наиболее эффективно. Собственно не понятно, чем разработчикам процессоров не приглянулись инструкции rep movsb/movsw/movsd что их так долго не оптимизировали.
Не знаю, но они это поняли наконец-то. Теперь, я думаю, такого зоопарка реализаций больше не будет.
Не первопричина, но важный фактор — в x86 с каждым новым семейством процессоров становится все больше команд, процессор становится все сложнее, в том числе усложняется декодер (узел, который из x86 делает микроинструкции). Процессор уже настолько сложен, что не так просто в нем оптимизировать какую-то конкретную вещь. А поскольку приоритеты часто задает маркетинг, то и возникают такие несчастные случаи, когда достаточно очевидная проблема годами не решается.
Интересно, как обстоят дела с rep movs у заклятых друзей Intel по x86-платформе.
Сорри, даже померять не на чем. Может, кто прокомментирует?
У Вас есть тесты? Только в исходниках ;)
Могу прогнать на Phenom X4 9650.
Windows 7 (32-разрядная).
См. коммент в конце треда.
Приветствую, Александр.
Таки хотелось бы посмотреть на цифры — насколько быстрее.
Детали на уровне микро — секрет? ;)
очень уж большая таблица получается (каждый год по микроархитектуре, и штук 5 memcpy). разница получается в 2-3 раза между лучшей и худшей реализацией для каждого проца.

Кроме того, микробенчмарк только из memcpy не так интересен, в реальном приложении еще дополнительные факторы, которые я указал в статье вступают в силу.
Интересно другое:
1. последний нехалем (впрочем SandyBridge устроит ;) ) и насколько rep movs быстрее самой быстрой среди известных сложных реализций копирования.
2. Что rep movs стал даже быстрее чем копирование через non temporal?
На sandy bridge сегодня могу протестировать.

у копирования через non temporal ограниченная применимость. Там, где применимо, оно, конечно, должно быть быстрее rep movs
Сергей, я запостил update.
Ага. :) Так и хочется побурчать про оформление результата — бери пример с Леши. ;)
> Цифра — во сколько раз самый продвинутый SSE4.1 код быстрее, чем std::memcpy, реализованный через rep movs
> Penryn — 1.6x
> Nehalem — 1.5x
> Sandy Bridge — 1.008x

1. Таки на Нехалеме лучше юзать SSE код — полтора раза это полтора раза. ;)

2. Сразу же вопрос, а таки если для SandyBridge сдеать AVX код? ;)
0. никогда не был силен в оформлении, ну, ты знаешь.
1 да.
2. не поможет, инфа 100%.
А давайте вы как-то подтвердите свои слова хотя бы конкретными цифрами, не говоря уже о повторяемых бенчмарках?

Потому что опровержений им вагон и маленькая тележка. Пока простой memcpy жарит окружающих раскаленным процессором, копируя картинку из одной области в другую, оптимизированная SSE-версия успевает сделать это раз в 20 быстрее. В 20 раз, а не в 2-3.
Я специально написал, что есть особый случай для non temporals/write combined памяти (которые и используются для копирования картинок по фреймбуфферам и memory mapped IO). Действительно, там возможна такая разница.

Для наиболее употребительного копирования нескольких килобайт в обычной памяти, могу прислать простой микро бенчмарк в личку. для виндов устроит, найдется nehalem/westmere/sandy bridge чтобы проверить?
при чём здесь какие-то фреймбуферы? О чём вы говорите?

Я писал про копирование картинки по обычной памяти для сжатия в H.264

Бенчмарки в личку — это просто какое-то неуважение. Впрочем, от виндового пользователя, который думает, что копированием нескольких килобайт можно что-то проверить ничего другого ждать и не приходится.

Фреймбуфер — один из сценариев, в котором на Sandy Bridge и последующих процессорах код копирования, реализованный на SSE4 будет существенно быстрее, чем на rep movs.

Вы спросили про бенчмарк, т.к. вы считаете, что мои даные и/или микро бенчмарк некорректны. Я был готов прислать исходник. Где здесь неуважение? Еще пара человек спросили, выслал и им.

Если для виндов не подходит, то для какой ОС? И кстати, что не так с пользователями, которые в числе прочих ОС пользуются и виндами?

Основной тезис моей статьи был, что давно rep movs был эффективным, потом появились гораздо лучшие SSE реализации, но недавно, по сути с Sandy Bridge и последующих, копирование при помощи rep mov, которое используется в ядре Linux и некоторых других продуктов(MSVC stdlib и тд) сравнялось по скорости с сложным SIMD кодом.

Из двух ваших комментариев, если я их правильно понял, следует противоположный тезис — ничего не изменилось, на процессорах Sandy Bridge, которые вышли примерно год назад, SIMD реализация копирования в 20 раз быстрее, чем rep movs.
Я свой бенчмарк (которым, по-вашему, ничего проверить нельзя) описал. Можно узнать подробности вашего? В вашем бенчмарке, где вы копируете картинку для последующего сжатия, у вас просто
memcpu(kartinka_dest, kartinka_src, kartinka_len_in_bytes);
или вы копируете как-то по линиям или еще как-то? Какого размера область памяти? Находится ли она уже в LLC?
Выложите проверяемые бенчмарки в статье с их результатами. Иначе все ваши слова с вашей недостатейкой в которой вы обманываете людей — полное фуфло. Впрочем, они и есть фуфло, потому что вы попросту не в теме и думаете, что копированием килобайта можно что-то намерять.

Запостил update, могу прислать код u-benchmark'а.
Во времена 8086 внутренняя реализация memcpy использовала 32-битные регистры esi, edi и ecx? ;)
да, тоже очень интересно с исторической т.з. Один из выводов из статьи — в начале 2000х на AMD железные префетчеры не справлялись даже с линейным паттерном доступа. Впрочем, я не уверен, что в те времена и на Pentium4 все было с этим в порядке.
Хорошие результаты, но все предсказуемо — при маленьких объемах вызов микрокода — относительно большие накладные расходы для фронт енда. При больших объемах — вызов амортизируется, фронт енду наоборот приходится декодировать лишние объемы кода, особенно если он не поместился в LSD.
Sign up to leave a comment.