Интересно, быстрее ли заменить ветвление на 2 умножения или нет (из-за штрафа за пропуск кеша)?
Вот мой случай:
float dot = rib1.x*-dir.y + rib1.y*dir.x;
if(dot<0){
dir.x = -dir.x;
dir.y = -dir.y;
}
И пытаюсь заменить на:
float dot = rib1.x*-dir.y + rib1.y*dir.x;
int sgn = (dot < 0.0) - (0.0 < dot ); //returns -1 or 1 (no branching here, tested)
dir.x *= sgn;
dir.y *= sgn;
2 ответа
Стоимость умножения зависит от нескольких факторов, от того, используете ли вы 32-битные или 64-битные числа с плавающей запятой, а также от того, включаете ли вы SSE или нет. Стоимость двух умножений с плавающей запятой составляет 10 циклов согласно этому источнику: http://www.agner.org /optimize/instruction_tables.pdf
Стоимость ветки также зависит от нескольких факторов. Как правило, не беспокойтесь о ветвях в вашем коде. Точное поведение предсказателя ветвления на ЦП будет определять производительность, но в этом случае вы, вероятно, должны ожидать, что ветвление будет в лучшем случае непредсказуемым, так что это может привести к множеству неверных предсказаний ветвления. Стоимость неверного предсказания ветки составляет 10-30 циклов согласно этому источнику: http: // valgrind .org / docs / manual / cg-manual.html
Лучший совет, который можно здесь дать, - это профилировать и тестировать. Я предполагаю, что на современном Core i7 два умножения должны быть быстрее, чем ветвь if the range of input varies sufficiently as to cause sufficient branch mispredictions as to outweigh the cost of the additional multiplication
.
Предполагая, что частота пропусков составляет 50%, стоимость перехода составляет в среднем 15 циклов (30 * 0,5), стоимость плавающего элемента составляет 10 циклов.
РЕДАКТИРОВАТЬ : добавлены ссылки, обновлена ориентировочная стоимость инструкции.
dot
из числа с плавающей запятой в целое число и sgn
из целого числа в число с плавающей запятой, вероятно, убьет производительность.
Ветвление не означает промахов в кэше: нарушается только предварительная выборка / конвейерная обработка инструкций, поэтому возможно, что вы заблокируете некоторую оптимизацию SSE во время компиляции.
С другой стороны, если используются только инструкции x86, спекулятивное выполнение позволит процессору чтобы правильно запустить выполнение наиболее часто используемой ветки.
С другой стороны, если вы вводите if в 50% случаев, вы находитесь в худшем состоянии: в этом случае я бы попытался найти конвейерную обработку SSE и оптимизировать выполнение с помощью SSE, вероятно, получая некоторые подсказки от этот пост в соответствии со вторым блоком кода.
Однако протестируйте свой код, проверьте созданный ассемблер, чтобы найти лучшее решение для этой оптимизации и получить правильное представление. И в конце концов держите нас в курсе :)
Похожие вопросы
Связанные вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.