2010-02-02 6 views
5

Hay Dear!Если заявление в C++

Я знаю, что оператор if является дорогостоящим оператором в C++. Я помню, как однажды мой учитель сказал, что если утверждение является дорогостоящим заявлением в смысле компьютерного времени.

Теперь мы можем делать все, используя инструкцию if на C++, поэтому это очень мощное утверждение в перспективе программирования, но оно дорого стоит в компьютерной перспективе.

Я начинающий и изучаю курс структуры данных после введения в курс C++. мой вопрос к вам
Является ли это лучше для меня, если выражение экстенсивно?

+1

Вы говорите, что вместо оператора if используется инструкция if? Что вы предлагаете использовать вместо этого? –

+1

Если оператор более экспансивный, чем + - * /, но он намного дешевле, чем цикл! поэтому используйте, когда вам это нужно :) – Tommy

+0

как можно «если» быть дорогим, его тест, за которым следует прыжок в случае еще только блока. Вот почему всегда ставьте код сразу после этого, если для большинства тестов этот тест является истинным. Умножение дороже. Поэтому, кто когда-либо говорил вам, «если» является дорогостоящим заявлением, вероятно, с технической поддержкой w.r.t, а не скоростью. – affan

ответ

13

Я не уверен, как вы можете обобщить, что утверждение if дорого.

Если у вас есть

if (true) { ... } 

тогда этого if наиболее likele быть оптимизирован прочь компилятором.

Если, с другой стороны, у вас есть ..

if (veryConvolutedMethodTogGetAnswer()) { .. } 

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

«если» сами по себе не являются «дорогостоящими» с точки зрения тактовых циклов.

5

Я бы сказал, многоif statement стоит дорого с точки зрения ремонтопригодности.

1

Вы должны написать свой код, чтобы быть правильным, понятным и простым в обслуживании. Если это означает использование заявлений if, используйте их! Мне было бы трудно поверить, что кто-то предложил вам не использовать заявление if.

Может быть, ваш инструктор имел в виду, что вы должны избегать что-то вроде этого:

if (i == 0) { 
    ... 
} else if (i == 1) { 
    ... 
} else if (i == 2) { 
    ... 
} ... 

В этом случае, возможно, было бы более логично было бы пересмотреть структуру данных и/или алгоритм, или, по крайней мере, использовать switch/case :

switch (i) { 
    case 1: ...; break; 
    case 2: ...; break; 
    ...; 
    default: ...; break; 
} 

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

Короткий ответ: используйте if, если и только если это имеет смысл!

0

С точки зрения компьютерного времени заявление «если» само по себе является одним из самых дешевых заявлений.

Просто не ставьте двадцать строк подряд, когда есть лучший способ, как переключатель или хеш-таблица, и все будет хорошо.

+0

Я нахожу это сомнительным. Там/есть/стоимость условной ветви, и она превосходит (например) базовую целочисленную арифметику. –

+0

Да, базовая целочисленная арифметика в настоящее время быстрее на 0,2 нс для обычного процессора, но «если» почти такая же быстрая - как правило, 0,5 нс в среднем, и большинство операций, таких как вызовы методов, запускаются сотнями наносекунд. Я утверждаю, что «если» является ** одним из ** самых дешевых заявлений. – RobC

17

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

Таким образом, да, они могут быть дорогими. Нет, вы вообще не должны беспокоиться об этом. Но Николай поднимает отдельную (хотя и справедливую) точку. Polymorphic code часто предпочтительнее (для ремонтопригодности) в случае, если или в случае необходимости

+0

Полностью согласен. Polymorphism rocks :) – ScaryAardvark

+0

Мэтью просто для уточнения, если прыжок сделан очень близко к текущей исполняемой инструкции, которая также должна присутствовать в кеше. это сделает, если еще дорого. Большинство из них, если прыгать на несколько инструкций.И во-вторых, вызов функции может привести к большему количеству времени, чем команда if, поскольку вызов функции требует сохранения параметра прохождения стека, а переход в другое место может быть далеко. – affan

+0

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

0

Вместо этого вы можете использовать Switch, что делает его более удобочитаемым, но я не уверен, если он быстрее. Если у вас есть что-то вроде:

if (condition1) { 
    // do something 
} else if (condition2) { 
    // do something 
} else if (condition3) { 
    // do something 
} else if (condition4) { 
    // do something 
} 

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

7

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

Если утверждения могут быть дорогими, поскольку они вынуждают компилятор генерировать инструкции ветвления. Если вы можете найти способ закодировать одну и ту же логику таким образом, что компилятор не должен вступать во все коды, вероятно, будет намного быстрее, даже если есть более точные инструкции. Я помню, как невероятно удивлялся тому, как перекодировать короткий фрагмент кода, чтобы использовать различные манипуляции с битами, а не делать какие-либо ветвления, ускоряя его в 10-20%.

Но это не повод избежать их вообще. Это просто то, что нужно помнить, когда вы пытаетесь вырезать последний бит скорости из раздела кода, который, как вы знаете, критичен по производительности, потому что вы уже запускали профайлер и другие инструменты, чтобы доказать это самому себе.

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

+0

+1, отметив, что преждевременная оптимизация - плохая идея – chrmue

2

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

В качестве примера, считая, сколько раз условие истинно (например, сколько чисел в векторе больше, чем 10000):

for (std::vector<int>::const_iterator it = v.begin(), end = v.end(); it != end; ++it) { 
    //if (*it > 10000) ++count; 
    count += *it > 10000; 
} 

версия, которая просто добавляет 1 или 0 в бегущем общем количестве может Быть небольшим количеством быстрее (я пробовал с 100 миллионами чисел, прежде чем я смог различить разницу).

Однако, с MinGW 3.4.5, с использованием алгоритма выделенный стандарт оказывается заметно быстрее:

count = std::count_if(v.begin(), v.end(), std::bind2nd(std::greater<int>(), 10000)); 

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

Другое место, где часто можно избежать оценки сложных условий, - это использование таблиц поиска (правило: алгоритмы часто могут выполняться быстрее, если вы позволяете им использовать больше памяти). Например, подсчет гласные (AEIOU) в слово-список, где вы можете избежать ветвления и оценки нескольких условий:

unsigned char letters[256] = {0}; 
letters['a'] = letters['e'] = letters['i'] = letters['o'] = letters['u'] = 1; 

for (std::vector<std::string>::const_iterator it = words.begin(), end = words.end(); it != end; ++it) { 
    for (std::string::const_iterator w_it = it->begin(), w_end = it->end(); w_it != w_end; ++w_it) { 
     unsigned char c = *w_it; 
     /*if (c == 'e' || c == 'a' || c == 'i' || c == 'o' || c == 'u') { 
      ++count; 
     }*/ 
     count += letters[c]; 
    } 
} 
0

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

FOR EACH i IN container 
    IF i < 100 
    i = 100 
    container.NEXT(i) 
END FOR 

производительность наиболее определяется container.NEXT(i); это намного дороже для связанных списков, а для смежных массивов. Для связанных списков это требует дополнительного доступа к памяти, который, в зависимости от кеша (ов), может занимать от 2,5 нс до 250 нс. Стоимость описания if будет измеряться в долях наносекунды.

0

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

if [%var1%] gtr [1543] 
     set var=1 
    else 
     set var=0 

эквивалентно

set /a var=%var1%/1543 

Я даже использовал гораздо более длинные выражения, со многими/и% операций, и это все еще было предпочтительнее, если заявление.

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