В справочном примере для макроса Q_LIKELY указан цикл и рассматривается ситуация, когда состояние false может возникнуть, как говорится, в одном случае на миллион:
// the condition inside the "if" will be successful most of the times
for(int i = 1; i <= 365; i++) {
if(Q_LIKELY(isWorkingDay(i))) {
...
}
...
}
В целом, эту пользу можно увидеть, учитывая не редкость ситуаций, когда в цикле проверяется значение, подразумевающее нахождение лишь в одном из двух состояний, и при этом одно из них практически всегда будет в подавляющем большинстве случаев.
Но сбивает с толку пример для Q_UNLIKELY, хотя и являющийся, судя по наименованию, всего лишь обратным вариантом:
bool readConfiguration(const QFile &file) {
// We expect to be asked to read an existing file
if(Q_UNLIKELY(!file.exists())) {
qWarning() << "File not found";
return false;
}
...
return true;
}
Какая тут может быть "помощь компилятору" в оптимизации кода, и если она всё-таки имеет место быть, то будет ли справедлива и для Q_LIKELY? Может быть существуют какие-либо критерии для определения характерных ситуаций, в которых использовании обозначенных макросов имеет смысл?
Ответ
В тексте ответа представлено моё субъективное мнение
Я считаю что эти макросы бесполезны в 99.99% случаев и должны применятся лишь после измерений, которые показали, что их использование оправдано. Почему? Потому что то, что сегодня «likely», может стать «unlikely» завтра, а программисты очень часто забывают менять вещи, которое явно не отражаются на программе. Таким образом, у нас может быть какая-то проверка помечена как Q_LIKELY, тогда как на самом деле всё наоборот. И это будет сбивать с толку программиста, который в дальнейшем будет это читать.
«Но как же так, это же оптимизация?!» — довольно спорное заявление, на самом деле, т.к. предсказатели ветвления(branch predictors) в CPU очень хороши, и чем тут реально сможет помочь компилятор непонятно. Вот возьмём цикл из вопроса, после первой же итерации, наиболее вероятно, что CPU начнёт выбирать инструкции по той ветке, что была в первой итерации. Что нам даст явное указание, потенциальный выигрыш в первой итерации? Смехотворно.
Всё это настолько нанооптимизации, что, повторюсь, прибегать к ним стоит лишь по нахождении проблемы с ветвлением, но не раньше. Программисты, помимо плохой памяти, ещё и не очень хороши в определении того, что же будет чаще(likely) исполняться.
Комментариев нет:
Отправить комментарий