C ++ Условная производительность оператора

У меня есть условное утверждение expensive_foo() что неверно в 99,9% случаев. И у меня есть условное утверждение bar что верно в ~ 50% случаев.

И я хочу, чтобы какое-то действие было сделано, если оба утверждения верны. Так что я почти наверняка знаю, что expensive_foo() ложно, и я хочу проверить это, только если bar правда.

Будет ли код ниже проверять expensive_foo() Только если bar правда? Или это проверит expensive_foo() каждый раз?

if ( bar && expensive_foo() )
{
...
}

Или мне нужно сделать такую ​​структуру:

if ( bar )
{
if ( expensive_foo() )
{
...
}
}

3

Решение

Логический оператор И && имеет короткое замыкание, что означает, что гарантируется, что второй операнд вычисляется тогда и только тогда, когда первый операнд оценивается как true, Условия if (bar && foo) а также if (bar) if (foo) идентичны

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

Таким образом, структура, вероятно, должна быть:

if (bar)
{
if (bool const foo = compute())   // expensive
{
// ...
}
}

Обратите внимание, что все эти конструкции означают, что мы можем или не можем вызвать compute(), Если вам требуется вызов функции безоговорочно, то вы должны сделать его первый проверять. В этом случае следует использовать успешное предсказание перехода на результат.

5

Другие решения

Оба кода проверим foo только в случае bar правда. В первом случае это гарантируется ленивым вычислением логических выражений (которое на самом деле может быть явно отключено в некоторых компиляторах, но включено по умолчанию).

2

Другие ответы хороши, но я подвергаю сомнению предпосылку.

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

В этом случае обычно можно попытаться организовать список по-другому, чтобы выполнить поиск O (logN) (или лучше) вместо O (N).
Я не знаю, сможете ли вы это сделать, но на этом я бы сосредоточился.

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

1

Я был бы удивлен, если бы оптимизированная сборка для обоих не была точно такой же. дорогой_foo () никогда не будет вызываться, если бар ложно.

1

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

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

  if ( bar && expensive_foo() )

Если в начале ставится менее дорогая булева функция, то мы можем сэкономить время.

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector