Я не знаю, почему ICC выбирает выравнивание стека по 2 строкам кэша:
and rsp, -128 #2.1
sub rsp, 128 #2.1
Это интересно. Кэш L2 имеет предварительный выборщик смежных строк, который любит перетягивать пары строк (в выровненной по 128 байтам группе) в L2. Но стековый фрейм main обычно не используется интенсивно. Возможно, там есть важные переменные в некоторых программах. (Это также объясняет настройку rbp
, чтобы сохранить старый RSP, чтобы он мог вернуться после ANDing. Gcc создает кадры стека с RBP в функциях, где он также выравнивает этот стек.)
Остальное, потому что main()
особенный, а ICC включает -ffast-math
по умолчанию . (Это один из «грязных» маленьких секретов Intel, позволяющий автоматически векторизовать больше кода с плавающей запятой из коробки).
Это включает в себя добавление кода в начало main
для установки битов DAZ / FTZ в MXCSR (регистр состояния / управления SSE). См. Руководства Intel x86 для получения дополнительной информации об этих битах, но они на самом деле не сложны:
DAZ: Денормалы - это ноль: в качестве входных данных для инструкции SSE / AVX денормали рассматриваются как ноль.
FTZ: Flush To Zero: при округлении результата инструкции SSE / AVX субнормальные результаты сбрасываются в ноль.
относящиеся: Опция SSE «Денормалы нули»
( ISO C ++ запрещает программе перезванивать в main()
, поэтому компиляторам разрешено помещать однократные данные в саму main
вместо файлов запуска CRT . Gcc / clang с -ffast-math
указано для связывания ссылки в файлах запуска CRT, которые устанавливают MXCSR, но при компиляции с помощью gcc / clang это влияет только на code-gen с точки зрения того, какие оптимизации разрешены, то есть обрабатывает FP add / mul как ассоциативную, когда разные временные значения означают это действительно не так. Это совершенно не связано с настройкой DAZ / FTZ).
Денормал используется здесь как синоним субнормального: значение FP с минимальным показателем степени и значением, где неявный начальный бит равен 0 вместо 1. т. Е. Значение с величиной, меньшей FLT_MIN
или DBL_MIN
, наименьшее представимое нормализованное float / double.
https://en.wikipedia.org/wiki/Denormal_number.
Инструкции, которые дают ненормальный результат, могут быть на намного медленнее: для оптимизации на задержку быстрый путь в некоторых аппаратных средствах предполагает нормализованные результаты и принимает помощь микрокода, если результат не может быть нормализован. Используйте perf stat -e fp_assist.any
для подсчета таких событий.
Из превосходной серии статей Брюса Доусона о FP: Это не нормально - производительность нечетных операций . Кроме того:
Агнер Фог провел некоторое тестирование (см. Его microarch pdf ) и отчеты для Haswell / Broadwell:
Недостаточное и субнормальное
Субнормальные числа возникают, когда операции с плавающей запятой близки к
опустошения. Обработка субнормальных чисел очень дорогая в некоторых
случаи, потому что субнормальные результаты обрабатываются микрокодом
исключения.
Хасвелл и Бродвелл имеют штраф около 124 часов.
циклы во всех случаях, когда операция над нормальными числами дает
субнормальный результат. Существует аналогичный штраф за умножение
между нормальным и субнормальным числом, независимо от того, является ли
результат нормальный или субнормальный. Там нет штраф за добавление нормального
и ненормальное число, независимо от результата. Там нет штрафа
для результатов переполнения, недостаточного заполнения, бесконечности или числа.
Штрафы за ненормальные числа избегаются, если "сбрасывать в ноль"
режим и режим «денормали-нуля» установлены в MXCSR
регистр.
Так что в некоторых случаях современные процессоры Intel избегают штрафов даже при ненормальных значениях, но