“ТО, ЕСЛИ” дорог?

85
задан Ayxan 1 March 2019 в 18:30
поделиться

14 ответов

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

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

Для [1 115] ответвление инструкции, однако, следующая инструкция, которая будет выполняться, не является следующим местоположением после текущей команды. Ответвления являются gotos - они говорят процессор, где следующая инструкция. Ответвления могут или быть условным выражением или безусловный, и целевое местоположение может быть или зафиксировано или вычислено.

Условное выражение по сравнению с безусловным легко понять - условный переход только взят, если определенное условие содержит (такой как, равняется ли одно число другому); если ответвление не взято, управление продолжается к следующей инструкции после ответвления как нормальный. Для безусловных переходов всегда берется ответвление. Условные переходы обнаруживаются в if операторы и контрольные испытания for и while циклы. Безусловные переходы обнаруживаются в бесконечных циклах, вызовах функции, функциональных возвратах, break и continue операторы, печально известное goto оператор и намного больше (эти списки являются совсем не исчерпывающими).

цель ответвления является другой важной проблемой. Большинство ответвлений имеет фиксированную цель ответвления - они переходят к определенному местоположению в коде, который фиксируется во время компиляции. Это включает if операторы, циклы всех видов, вызовов регулярной функции, и многое другое. Вычисленный ответвления вычисляют цель ответвления во времени выполнения. Это включает switch операторы (иногда), возвращаясь из функции, вызовов виртуальной функции и вызовов указателя функции.

Поэтому, что это все означает для производительности? Когда процессор видит, что команда перехода появляется в ее конвейере, он должен выяснить, как продолжить заполнять ее конвейер. Для выяснения, какие инструкции появляются после ответвления в потоке программы это должно знать две вещи: (1) если ответвление будет взято и (2) цель ответвления. Понимание этого называют предсказание ветвлений , и это - сложная проблема. Если процессор предполагает правильно, программа продолжается в полной скорости. Если вместо этого предположения процессора неправильно , это просто провело некоторое время, вычисляя неправильную вещь. Это теперь должно сбросить свой конвейер и перезагрузить его с инструкциями от корректного пути выполнения. Нижняя строка: большой хит производительности.

Таким образом, причина, почему, если операторы являются дорогими, происходит из-за [1 126] mispredictions ответвления. Это только на самом низком уровне. Если Вы пишете высокоуровневый код, Вы не должны волноваться об этих деталях вообще. Необходимо только заботиться об этом, если Вы пишете чрезвычайно критический по отношению к производительности код в C или блоке. Если это так, запись кода без ответвлений может часто превосходить код, который переходит, даже если необходимы еще несколько инструкций. Существуют некоторые прохладные приемы битового жонглирования, которые можно сделать для вычисления вещей такой как abs(), min(), и max() без ветвления.

168
ответ дан Adam Rosenfield 24 November 2019 в 08:09
поделиться

Самое дорогое с точки зрения использования ALU? Это израсходовало регистры ЦП для хранения значений, которые будут сравнены, и занимает время, чтобы выбрать и сравнить значения каждый раз, если оператор выполняется.

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

Просто попытка интерпретировать Ваши недостающие слова.

-1
ответ дан 24 November 2019 в 08:09
поделиться

Также обратите внимание, что в цикле не обязательно очень дороги.

современный ЦП принимает после первого посещения оператора "if", что "если-тело" должно быть взято (или сказал другой путь: это также предполагает, что тело цикла взято многократно) (*). После вторых и дальнейших посещений это (ЦП) может, возможно, изучить Таблица истории переходов и видеть, как условие было прошлым разом (действительно ли это было верно? действительно ли это была ложь?). Если это была ложь в прошлый раз, то спекулятивное выполнение "еще" продолжится к если, или вне цикла.

(*) правило на самом деле" вперед ответвление, не взятое, ветвление назад, взятое ". В операторе "if", существует только [вперед] переход (к точке после того, как если-тело ), если условие оценивает ко лжи (помните: ЦП так или иначе принимает для не взятия ответвления/перехода), но в цикле, существует, возможно, вперед ответвление к позиции после цикла (чтобы не быть взятым), и ветвление назад после повторения (чтобы быть взятым).

Это - также одна из причин, почему вызов к виртуальной функции или вызову указателя функции не то, что хуже, поскольку многие принимают ( http://phresnel.org/blog/ )

4
ответ дан Sebastian Mach 24 November 2019 в 08:09
поделиться

У меня был этот спор с моим другом однажды. Он использовал очень наивный круговой алгоритм, но утверждал его быть быстрее, чем мой (Вид, который только вычисляет 1/8-й из круга), потому что шахта использовала если. В конце, если оператор был заменен sqrt и так или иначе который был быстрее. Возможно, потому что FPU имеет встроенный sqrt?

0
ответ дан Demur Rumed 24 November 2019 в 08:09
поделиться

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

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

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

4
ответ дан Michael Burr 24 November 2019 в 08:09
поделиться

Центральные процессоры являются глубоко конвейерными. Любая команда перехода (if/for/while/switch/etc) означает, что ЦП действительно не знает что инструкцию загрузиться и работать затем.

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

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

Удача в классе.

кроме того, если необходимо волноваться об этом в реальной жизни, Вы, вероятно, делаете дизайн ОС, графику в реальном времени, научные вычисления или что-то столь же Зависящее от ЦП. Профиль перед волнением.

3
ответ дан tfinniga 24 November 2019 в 08:09
поделиться

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

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

4
ответ дан David Thornley 24 November 2019 в 08:09
поделиться

Возможно, ветвление уничтожает упреждающую выборку инструкции по ЦП?

6
ответ дан activout.se 24 November 2019 в 08:09
поделиться

if сам по себе не медленные. Замедление всегда относительно, я держал пари для своей жизни, что Вы никогда не чувствовали "издержки" оператора "if". Если Вы собираетесь сделать высокоэффективный код, Вы могли бы хотеть избежать ответвлений так или иначе. То, что делает if медленный, - то, что процессор предварительно загружает код от после if на основе некоторой эвристики и этажерки. Это будет также мешать конвейерам выполнить код непосредственно после if команда перехода в машинном коде, так как процессор еще не знает, какой путь будет взят (в конвейерном процессоре, многоадресные команды чередованы и выполнены). Выполняемому коду придется выполнить наоборот (если другое ответвление было взято. это звонило branch misprediction), или noop быть заполненным в тех местах так, чтобы этого не происходило.

, Если if является злым, то switch является злым также, и &&, || также. Не волнуйтесь об этом.

7
ответ дан Johannes Schaub - litb 24 November 2019 в 08:09
поделиться

Проверьте статью Лучшая Производительность Посредством Устранения Ответвления на Производительности Ячейки. Другой забава каждый это сообщение о выборах без веток на Оперативном Блоге Обнаружения коллизий.

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

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

10
ответ дан Parappa 24 November 2019 в 08:09
поделиться

На самом низком уровне if состоит из (после вычисления всех определенных для приложения предпосылок для конкретного if):

  • некоторая тестовая инструкция
  • переход к некоторому месту в коде, если тест успешно выполняется, продолжите двигаться вперед иначе.

Затраты, связанные с этим:

  • низкоуровневое сравнение - обычно 1 эксплуатация CPU, супер дешевый
  • потенциальный переход - который может быть дорог

Reson, почему переходы являются дорогими:

  • можно перейти к коду arbirary, который живет где угодно в памяти, если оказывается, что это не кэшируется CPU - у нас есть проблема, потому что мы должны получить доступ к оперативной памяти, которая является медленнее
  • , современные центральные процессоры действительно переходят предредактирование. Они пытаются предположить ли, если будет следовать или не и выполнять код вперед в конвейере, поэтому ускорять вещи. Если прогноз перестал работать, все вычисление, сделанное вперед конвейером, должно делаться недействительным. Это также - дорогая операция

Так для подведения:

  • , Если может быть expesive, если Вы действительно, действительно, действительно заботитесь о производительности.
  • необходимо заботиться об этом , если и только если Вы пишете оперативный трассировщик лучей или биологическое моделирование или что-то подобное. Нет никакой причины заботиться об этом в большей части реального мира.
7
ответ дан Marcin 24 November 2019 в 08:09
поделиться

Ответвления, особенно на микропроцессорах архитектуры RISC, являются некоторыми самыми дорогими инструкциями. Это вызвано тем, что на многой архитектуре, компилятор предсказывает, какой путь выполнения будет взят, скорее всего, и помещает те инструкции затем в исполняемый файл, таким образом, они уже будут в кэше ЦП, когда ответвление произойдет. Если ответвление идет другим путем, оно должно вернуться к оперативной памяти и выбрать новые инструкции - это довольно дорого. На многой архитектуре RISC все инструкции являются одним циклом за исключением ответвления (который часто является 2 циклами). Мы не говорим о крупной стоимости здесь, не волнуйтесь об этом. Кроме того, компилятор оптимизирует лучше, чем Вы делаете 99% времени:) Одна из действительно потрясающих вещей об архитектуре EPIC (Itanium является примером) - то, что это кэшируется (и начинает обрабатывать), инструкции с обеих сторон ответвления, затем отбрасывает набор, в котором это не нуждается, как только результат ответвления известен. Это сохраняет доступ дополнительной памяти типичной архитектуры, если он переходит вдоль непредсказанного пути.

14
ответ дан rmeador 24 November 2019 в 08:09
поделиться

Оператор "Expensive" is a very relative term, especially with relationship to an "if", так как также необходимо взять в учетную запись стоимость условия. Это могло расположиться где угодно от нескольких коротких инструкций по CPU до тестирования результата функции, которая обращается к удаленной базе данных.

я не волновался бы об этом. Если Вы не делаете встроенное программирование, Вы, вероятно, не должны быть обеспокоены стоимостью" if" вообще. Для большинства программистов это просто не идет в никогда быть ведущим фактором в производительности Вашего приложения.

16
ответ дан Joel Coehoorn 24 November 2019 в 08:09
поделиться

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

я думаю о нем как о длинном грузовом поезде. Это может нести много груза быстро в прямой линии, но это образовывает угол плохо.

(Prescott) Pentium 4 имел заметно длинный конвейер 31 этапа.

[еще 114] на Википедия

6
ответ дан Guge 24 November 2019 в 08:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: