Пример:
if (almost_always_false_condition) {
// do something
}
Есть ли способ предложить компилятор, который в 99%-м условии будет ложным. Вычисление условия берет ~60 циклов, которые будут проверены, и оно не может быть вычислено во время компиляции самим компилятором.
(gcc 4.3)
Если вы хотите предложить GCC, что условие, вероятно, будет иметь заданное значение как подсказку для аранжировки потока кода, вы должны использовать __ STOVELIN_EXPECT ()
:
if (__builtin_expect(almost_always_false_condition,0)) {
// do something
}
Тем не менее, звучит так, как вы хотите найти способ избежать оценки состояния, который __ STOVELS_EXPECT ()
не будет. Есть ли способ, которым вы можете быстро приблизить состояние, и только выполнить полную проверку, когда приближение верно:
if (__builtin_expect(fastCheckThatIsTrueIfFullConditionIsTrue,0)) {
// most of the time, we don't even get to here, so you don't need
// to evaluate the condition
if (almostAlwaysFalseCondition) {
// do something
}
}
Можете ли вы рассказать нам больше о том, что это состояние?
Если результат может варьироваться в течение одного прогона, вы можете использовать ленивую оценку логических операторов, чтобы разделить состояние в дешевую часть и дорогостоящую часть и сначала запускать дешевую часть.
if (a == 5 && somethingexpensive())
{
...
}
С момента вычисления A == 5
дешевле, чем что-тоэксплуатация ()
, и если оно почти всегда FALSE
, вы должны запустить его первым, что позволяет избежать оценки Статья , что оговорное
.
Если с другой стороны, результат постоянна для прогона программы, вы можете оптимизировать его, сохраняя результат расчета в статической или глобальной переменной.
static int result = doevalfunctiononlyonce();
if (result)
{
....
}
Таким образом, вы сократили стоимость , если
к простому поиску памяти.
Если условие меняет только изменения в ответ на действие в другой процедуре, вы можете обновить глобальную процедуру:
int condition;
void appendToList(int a)
{
list.append(a);
if (list.somethingexpensive())
{
condition = true;
} else
{
condition = false;
}
}
void someotherfunction()
{
// if (list.somethingexpensive())
if (condition)
{
...
}
}
Это полезно, если Comertherfunction
называется большим количеством Функция AppendTolist
.
Документация предполагает, что GCC делает (или может) выполнять оптимизацию, ориентированную на профиль. Это не то, что я когда-либо пытался сделать с GCC, поэтому не может предоставить никаких дополнительных советов, это может быть стоить вашего во время удара Google.
Прежде всего, сколько циклов проводится в , а также пункт
или в другом месте в программе? Если вы выполните StackShots , вы тратите ли вы как минимум 10% вашего времени в этом тесте? Если нет, там, вероятно, больше проблем, вы должны посмотреть сначала.
Во-вторых, если вы тратите> 10% времени в этом тесте, вы должны посмотреть, как можно скорее настроить алгоритм, чтобы иметь точки принятия решений, ближе к 50-50 вероятности. Оччество принятия решений 50-50 дает 1 бит информации, когда она выполняется, в то время как начальник принятия решения 99-1 дает только около 0,07 бита. * (Т. Е. Это не говорит вам много, поэтому это неэффективное использование циклов ЦП. ) Пример этого явления - это если вы сравните линейный поиск с двоичным поиском.
* Если у вас есть точка бинарного решения, а вероятности результатов A
и B
, выходной выход (энтропия) в битах - (A * Журнал (а) + b * log (b)) / log (2)
.