Автор блога NukeTheBees решил проверить, как разные компиляторы оптимизируют преобразование 1D-индекса в 3D-координаты сетки. Эта частая задача требует вычисления как частного, так и остатка от деления.
Архитектура x86 позволяет сделать это максимально эффективно - всего двумя инструкциями
idiv (она одновременно вычисляет и частное, и остаток, помещая их в разные регистры). Автор протестировал два подхода на C++:1️⃣ Стандартные операторы
/ и %2️⃣ Использование функции
std::div📊 Что показали компиляторы?
🔹 Вариант с операторами (
/ и %):🏆 Clang сгенерировал идеальный код: всего 2 инструкции
idiv и никаких лишних обращений к памяти.🥈 GCC тоже справился за 2
idiv, но зачем-то скинул промежуточные результаты в стек перед возвратом.❌ MSVC оплошал и выдал избыточную третью инструкцию деления при вычислении
y.🔹 Вариант с
std::div (в надежде помочь компилятору):✅ MSVC резко исправился, заинлайнил вызовы и выдал те самые оптимальные 2
idiv.❌ Зато Clang и GCC внезапно отказались инлайнить
std::div! В итоге они сгенерировали настоящие вызовы функций (call div), что из-за накладных расходов делает этот код медленнее первого варианта.💡Ни один из подходов на C++ не смог заставить все три компилятора выдать идеальный машинный код. Поэтому для критически важных участков производительности не стоит слепо доверять компилятору - всегда заглядывайте в сгенерированный ассемблер (например, через Compiler Explorer).
🔗 Подробный разбор ассемблерного кода читайте в статье: https://nukethebees.com/int-division-modulo-optimisation-differences-clang-gcc-msvc/
♻️ Сделай репост, чтобы помочь другим.
📲 Мы в MAX
👉 @Bookflow
