Миша пишет код
@misha_writes_code
Смотрел тут свежее выступление Годболта. Он рассказывает про всякие фичи Compiler Explorer - много всего интересного, но удивил меня следующий прикол.
Если написать алгоритм подсчета единичных битов в числе, то компилятор догадается переписать весь этот код просто в одну инструкцию popcnt.
НО!
Загадка:
Если дополнительно указать компилятору, что код нужно собирать именно под skylake, то неожиданно, помимо
https://godbolt.org/z/hYG7zEs4Y
Разгадка:
Процессор изо всех сил старается выполнить код как можно быстрее, поэтому мутит разные оптимизации - переименовывает регистры, выполняет инструкции в другом порядке и тп. Чтобы такие оптимизации оставались легальными, существует ряд правил их применения. В частности, у инструкций есть зависимости от регистров: если значение регистра еще не готово, то инструкцию, которая его использует, исполнять нельзя.
И в данном семействе процессоров была особенность (баг), которая добавляла лишнюю зависимость к инструкции popcnt.
Чтобы эту зависимость уничтожить, уже компилятор вынужден на своей стороне дополнительно что-то предпринимать. По-видимому, самое простое и дешевое - вставить зануление регистра через
В итоге получается интересная ситуация: на первый взгляд лишняя инструкция должна замедлить выполнение, а она наоброт ускоряет.
P.S.
Меня еще удивило, что на вопрос со сцены "а почему там появился лишний xor", в зале нашелся человек, который корректно на это ответил. Видимо, это какая-то популярная тема и только я как всегда был не в курсе.
Всякие ссылки по теме:
- фикс в clang: https://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20160215/332717.html
- фикс в gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62011
- исходный вопрос на stackoverflow: https://stackoverflow.com/questions/25078285/replacing-a-32-bit-loop-counter-with-64-bit-introduces-crazy-performance-deviati
- и еще ответ со списком похожих проблем:
https://stackoverflow.com/a/70649222
Если написать алгоритм подсчета единичных битов в числе, то компилятор догадается переписать весь этот код просто в одну инструкцию popcnt.
НО!
Загадка:
Если дополнительно указать компилятору, что код нужно собирать именно под skylake, то неожиданно, помимо
popcnt dst, src, там появляется еще и xor dst, dst, который выглядит лишним, ведь popcnt не использует dst в вычислениях, а просто кладет туда результат. Зачем же он тогда нужен?https://godbolt.org/z/hYG7zEs4Y
Разгадка:
Процессор изо всех сил старается выполнить код как можно быстрее, поэтому мутит разные оптимизации - переименовывает регистры, выполняет инструкции в другом порядке и тп. Чтобы такие оптимизации оставались легальными, существует ряд правил их применения. В частности, у инструкций есть зависимости от регистров: если значение регистра еще не готово, то инструкцию, которая его использует, исполнять нельзя.
И в данном семействе процессоров была особенность (баг), которая добавляла лишнюю зависимость к инструкции popcnt.
popcnt dst, src зависела не только от src, но также и от dst. Из-за чего инструкция могла выполняться заметно дольше, потому что ждала фантомную зависимость от dst. Чтобы эту зависимость уничтожить, уже компилятор вынужден на своей стороне дополнительно что-то предпринимать. По-видимому, самое простое и дешевое - вставить зануление регистра через
xor dst, dst, который гарантированно изменит его значение и сломает цепочку зависимостей.В итоге получается интересная ситуация: на первый взгляд лишняя инструкция должна замедлить выполнение, а она наоброт ускоряет.
P.S.
Меня еще удивило, что на вопрос со сцены "а почему там появился лишний xor", в зале нашелся человек, который корректно на это ответил. Видимо, это какая-то популярная тема и только я как всегда был не в курсе.
Всякие ссылки по теме:
- фикс в clang: https://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20160215/332717.html
- фикс в gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62011
- исходный вопрос на stackoverflow: https://stackoverflow.com/questions/25078285/replacing-a-32-bit-loop-counter-with-64-bit-introduces-crazy-performance-deviati
- и еще ответ со списком похожих проблем:
https://stackoverflow.com/a/70649222
🔥 11
👍 3
😁 3
8 904
Обсуждение 0
Обсуждение не доступно в веб-версии. Чтобы написать комментарий, перейдите в приложение Telegram.
Обсудить в Telegram