Я заметил интересное явление вокруг флагов компоновщика компилятора, влияющих на работающий код способами, которые я не могу понять.
У меня есть библиотека, в которой представлены разные реализации одного и того же алгоритма, чтобы проверить скорость работы этих разных реализаций.
Сначала я протестировал ситуацию с парой идентичных реализаций, чтобы убедиться, что все произошло правильно (обе работали примерно с одинаковой скоростью). Я начал с компиляции объектов (по одному на реализацию) со следующими флагами компилятора:
-g -funroll-loops -flto -Ofast -Werror
а затем при линковке передал gcc следующие флаги:
-Ofast -flto=4 -fuse-linker-plugin
Это дало библиотеку, которая работала молниеносно быстро, но, что любопытно, была надежно и повторяемо ~ 7% быстрее для первого объекта, который был включен в аргументы во время компоновки (поэтому любая реализация была бы быстрее, если бы она была связана первой).
так с:
gcc -o libfoo.so -O3 -ffast-math -flto=4 -fuse-linker-plugin -shared support_obj.os obj1.os obj2.os -lm
vs
gcc -o libfoo.so -O3 -ffast-math -flto=4 -fuse-linker-plugin -shared support_obj.os obj2.os obj1.os -lm
в первом случае реализация в obj1 работала быстрее, чем реализация в obj2. Во втором случае было верно обратное. Чтобы было ясно, код идентичен в обоих случаях, за исключением имени записи функции.
Теперь я удалил эту странную разницу в порядке ссылок и аргументов (и фактически немного ускорил ее), удалив флаг -Ofast
во время связывания.
Я могу воспроизвести в основном ту же ситуацию, изменив -Ofast
на -O3 -ffast-math
, но в этом случае мне нужно указать -ffast-math
во время связывания, что снова приводит к странной разнице в скорости упорядочения. Я не уверен, почему ускорение поддерживается для -Ofast
, но не для -ffast-math
, когда -ffast-math
не передается во время компоновки, но я могу допустить, что это может быть связано с оптимизацией времени компоновки, передающей соответствующую информацию в одном случае, но не в другом. . Однако это не объясняет разницы в скорости.
Удаление -ffast-math
означает, что он работает примерно в 8 раз медленнее.
Кто-нибудь может пролить свет на то, что может происходить, чтобы вызвать этот эффект? Мне очень интересно узнать, что может вызвать такое забавное поведение, чтобы я не мог случайно вызвать его в будущем.
Тест скорости выполнения выполняется в python с использованием оболочки вокруг библиотеки и timeit, и я почти уверен, что это правильно (я могу менять порядок и вещи, чтобы показать, что побочные эффекты python незначительны).
Я также проверил библиотеку на правильность вывода, так что я тоже могу быть достаточно уверен в этом.
-Ofast
включает все оптимизации, описанные в-O3
и-ffast-math
, документация не исключает возможности того, что она также включает другие оптимизации, которые ими не охвачены - возможно, даже те, которые недоступны каким-либо другим образом. В той мере, в какой ваш вопрос заключается в том, почему поведение-Ofast
отличается от поведения-O3 -ffast-math
, это, вероятно, как-то связано с этим. - person John Bollinger   schedule 18.12.2015ld
один изbinutils
- person too honest for this site   schedule 18.12.2015-mtune=native
, что, кажется, в значительной степени устраняет любую разницу (хотя все еще ~ 2% или около того). Устанавливает лиmtune
выравнивание стека? Какие параметры могут привести к тому, что одинаковые биты c не будут работать с одинаковой скоростью? (Стоит отметить, что сборка в обоих случаях не совсем идентична, хотя и близка). - person Henry Gomersall   schedule 18.12.2015