#c #c #optimization #sse #intrinsics
#c #c #оптимизация #sse #встроенные
Вопрос:
Некоторое время назад я где-то читал, что встроенные функции SSE компилируются в эффективный машинный код, потому что компиляторы обрабатывают их иначе, чем обычные функции. Я размышляю о том, как на самом деле компиляторы это делают и что программисты C могут сделать, чтобы облегчить процесс. Существуют ли какие-либо рекомендации о том, как использовать встроенные функции таким образом, чтобы облегчить работу компилятора по генерации эффективного машинного кода.
Спасибо.
Ответ №1:
Вопреки тому, что написал Necrolis, встроенные функции могут компилироваться вплоть до инструкций, которые они представляют, а могут и не компилироваться. Это особенно верно для инструкций копирования или загрузки, таких как _mm_load_pd
, поскольку компилятор по-прежнему отвечает за распределение регистров и присвоение при использовании встроенных функций. Это означает, что копирование значения из одного местоположения в другое может вообще не потребоваться, если два местоположения могут быть представлены одним и тем же регистром. В этом случае компилятор может удалить копию. Он также может удалить другие инструкции, если результат никогда не используется.
Ознакомьтесь с этим сообщением в блоге, где поведение разных компиляторов сравнивается на практике. Это с 2009 года, поэтому детали могут больше не применяться. Однако более новые компиляторы, скорее всего, будут оптимизировать ваш код больше, а не меньше.
Что касается фактического эффективного использования встроенных функций, ответ тот же, что и для всей другой оптимизации производительности: измерять, измерять и измерять. Убедитесь, что вы действительно имеете дело с горячей частью кода, выясните, почему она медленная, а затем улучшите ее. Вы, скорее всего, обнаружите, что улучшение ваших шаблонов доступа к памяти важнее, чем использование встроенных.
Комментарии:
1. Я полностью согласен с вами. Простой пример — умножение матрицы, транспонирование первой матрицы может значительно увеличить доступ к памяти.
Ответ №2:
Встроенные функции компилируются вплоть до инструкций, которые они представляют, независимо от того, эффективно это или нет, зависит от того, как они используются.
кроме того, каждый компилятор обрабатывает встроенные функции немного по-разному (то есть зависит от его реализации), но GCC имеет открытый исходный код, поэтому вы можете видеть, как они обрабатывают функции SSE, Open Watcom *, LCC, PCC и TCC * являются компиляторами C с открытым исходным кодом, хотя у них нет встроенных функций SSE, они все равно должны иметь встроенные функции, и вы можете видеть, как они их обрабатывают.
Я думаю, что то, что вы прочитали, было связано с автоматической векторизацией кода, в чем GCC (см. Это) и ICC очень хороши, но они не так хороши, как оптимизированный вручную код, по крайней мере, пока
* возможно, была обновлена поддержка SSE, но в последнее время не проверял…
Комментарии:
1. Я имею в виду функции _mm_blah_blah, а не автоматическую векторизацию. Хотел бы я прочитать исходный код GCC.
2. @pic11: тогда просто игнорируйте последний бит. Я согласен с вами, хотя, к сожалению, исходный код gcc является беспорядочным с точки зрения читателей (именно поэтому я предложил более простые компиляторы c), вы могли бы найти LLVM (и clang), которые также проще выбирать. Однако у Gcc и llvm есть много сопроводительных документов, так что вы можете найти некоторые, относящиеся к sse (был отличный раздел распределения регистров ssa, в котором упоминались оптимизации для sse). В блоге msdn visual Studio есть несколько записей об их встроенных функциях simd, но, к сожалению, они очень поверхностны…
3. Хотя gcc — это беспорядок и настоящее испытание для компиляции (компилировать компилятор, а не компилироваться с помощью компилятора), это один из самых удивительных компиляторов в мире. Особенно с точки зрения оптимизации внутри встроенных функций и вокруг них, он превосходит MSVC по длине.
4. Принято, даже если это не дает прямого ответа на вопрос. Похоже, изучение того, что компиляторы делают под капотом, — единственный способ понять, как работают встроенные функции. Хотелось бы, чтобы была какая-нибудь книга «Эффективный SSE» (похожая на «Эффективный C «), которая объясняла бы встроенные функции SSE, не беспокоя обычные коды C скрытыми внутренними компонентами компиляторов.