состояние против деления - PullRequest
8 голосов
/ 13 января 2012

с учетом следующего оператора, который выполняется много:

iNormVal = iVal / uRatio;

будет ли целесообразнее следующее (с точки зрения производительности), если uRatio == 1 большую часть (90%) времени?

if(uRatio > 1)
iNormVal = iVal / uRatio;
else
iNormVal = iVal;

спасибо ..

Ответы [ 6 ]

7 голосов
/ 13 января 2012

Поскольку вы заметили это как потенциальное узкое место, очень вероятно, это место совершенно не имеет значения для общей скорости вашего приложения.Серьезно, люди, даже программисты-гуру, как известно, плохо умеют замечать настоящие узкие места.(Разница в том, что хорошие программисты признают и проповедуют это, в то время как юниоры продолжают тратить время на оптимизацию нерелевантных мест.)

В целом этот подход к оптимизации оказался наиболее полезным:

  1. Если скоростьЭто серьезная проблема, запланируйте значительное время для оптимизации перед выпуском вашего приложения.
  2. Создайте ваш код, чтобы он не сопровождался внутренними пессимизациями.
  3. Реализуйте так, чтобы легче всего было понять код.Предотвращение очевидных пессимизаций (например, передача параметров по значению вместо ссылки), но не перевозбуждение.
  4. Проверьте , если он слишком медленный.Если это так, профиль приложение и определить горячие точки.
  5. Поместите ресурсы в , оптимизируя (и, следовательно, потенциально запутывая ) только эти горячие точки, итеративно профилируя, чтобы проверить, какие изменения помогают.
  6. Остановитесь, когда приложение будет достаточно быстрым.

(Очевидно, что для библиотечного кода все по-другому, но эти несколько шагов унесут вас далеко).

4 голосов
/ 13 января 2012

Вам нужно профиль это, чтобы получить измерение, слишком сложно угадать. Компилятор может решить, что вы не правы, и удалить тест, так что проверяйте с оптимизацией и без нее.

Фактическая стоимость (целочисленного) деления может быть довольно низкой, особенно на современных процессорах настольного класса. Согласно этого PDF затраты на современные (Wolfdale / Nehalem / Sandy Bridge) 32/32-битного деления составляют 14-23 / 17-28 / 20-28 циклов соответственно. Так что, если вы действительно много делаете, это может сложиться. В этом случае, если возможно, посмотрите на параллельные (векторизованные) опции.

Я бы постарался избежать этого, если это вообще возможно, поскольку он вводит ветку. Ветви имеют два недостатка: они делают код более сложным, вводя несколько путей, которые должен понимать программист, читающий код, и могут также накладывать накладные расходы на выполнение.

2 голосов
/ 13 января 2012

Если вы решите пойти с ветвлением, то можете сначала проверить общий случай. Это немного более читабельно и должно быть немного лучше в плане производительности.

if(uRatio <= 1) {
    iNormVal = iVal;
}
else {
    iNormVal = iVal / uRatio;
}

Чтобы быть более читабельным, вы можете добавить локальную переменную с хорошим именем, которая содержит результат выражения.

unsigned int uSmallRatio = uRatio <= 1;
if(uSmallRatio) {
    iNormVal = iVal;
}
else {
    iNormVal = iVal / uRatio;
}

Компилятор может оптимизировать это в тот же машинный код, что и первый подход. Хотя я не уверен в этом.

Точно так же вы могли бы сделать это, но это не красиво:

iNormVal = uRatio <= 1 ? iVal : iVal / uRatio;

Наконец, другой подход будет:

iNormVal = iVal;
if(uRatio > 1) { /*explain why you do this so it won't be changed by somebody else*/
    iNormVal = iVal / uRatio;
}

Я уверен, что есть и другие подходы, которые стоит рассмотреть.

Привет ...

2 голосов
/ 13 января 2012

Это зависит.

Является ли код в приложении, критичном к производительности? Если так, то это может помочь. Если не хорошо, то я обычно ошибаюсь в сторону или читабельности и не представляю дополнительного оператора if.

Даже если это приложение, критически важное для производительности, это обычно внешние взаимодействия, которые составляют 95% времени выполнения, такие как взаимодействия с базами данных или внешними службами. Компиляторы обычно выполняются очень быстро и если операторы очень дешевы. Когда мы обычно профилируем наш код, мы редко вносим изменения, такие как то, что вы описали только по причинам совершенства. Неправильное использование циклов и т. П. Иногда может способствовать, но мы редко добавляем, если такие утверждения, как описано.

Надеюсь, это поможет ...

1 голос
/ 13 января 2012

Большинство проблем с производительностью либо идеологические (вы неправильно спроектировали), либо реализация проверенного более медленного алгоритма (предоставленный выбор).

Кроме того, прирост производительности будет на уровне сборки и будет зависеть от платформы.

Я вряд ли могу рекомендовать это в качестве фактической проблемы с производительностью, если вы действительно не стеснены в производительности, и в этот момент вам нужно сначала проверить вышеуказанное.

Все, что вы сделали, это подняли брови человека, который будет поддерживать ваш код. Надеюсь, у вас есть ленивый программист, который оставляет вещи в покое, или вы все равно потеряете этот код.

Поскольку на этом уровне у вас нет гарантий того, как код будет работать на разных платформах при разных компиляторах, опциях компилятора и оптимизации, вы можете даже потерять код для оптимизации компилятора. Лучше сосредоточиться на более крупных вопросах.

1 голос
/ 13 января 2012

Предложение if скорее всего замедлит работу программы. Ветвление - очень плохо для производительности, потому что современные процессоры конвейеризованы , а ветвления препятствуют полной эффективности конвейера. Это настолько серьезная проблема, что предсказание ветвления требует значительных усилий, но в этом случае это не поможет. Даже если прогноз верен в 90% случаев, это означает, что пустой конвейер в 10% случаев, что намного хуже, чем деление типа int (особенно если учесть, что само предложение if требует времени).

Но, скорее всего, это вообще не имеет значения, потому что ваш код проводит большую часть своего времени в совершенно другом месте, что делает весь этот вопрос огромной тратой времени.

...