Предсказание ветвей в наши дни чертовски хорошее. Но это не значит, что штрафы за ветки могут быть устранены.
В типичном коде вы, вероятно, получаете более 99% правильных прогнозов, и все же снижение производительности все еще может быть значительным. В этом есть несколько факторов.
Одним из них является простая задержка ветвления. На обычном процессоре ПК это может быть порядка 12 циклов для неверного прогноза или 1 цикла для правильно предсказанной ветви. Ради аргумента, давайте предположим, что все ваши ветви правильно предсказаны, тогда вы свободны дома, верно? Не совсем.
Простое существование ветки подавляет много оптимизаций.
Компилятор не может эффективно переупорядочивать код по веткам. Внутри базового блока (то есть блока кода, который выполняется последовательно, без ветвей, одной точки входа и одного выхода), он может переупорядочивать инструкции по своему усмотрению, если сохраняется значение кода, потому что они Все рано или поздно будут казнены. Через филиалы становится сложнее. Мы могли бы переместить эти инструкции вниз для выполнения после этой ветви, но тогда как мы можем гарантировать, что они будут выполнены? Положить их в обе ветви? Это дополнительный размер кода, он также беспорядочный, и он не масштабируется, если мы хотим переупорядочить более чем одну ветвь.
Ветви все еще могут быть дорогими, даже с лучшим прогнозом ветвления. Не только из-за неправильных прогнозов, но и потому, что планирование инструкций становится намного сложнее.
Это также означает, что важным фактором является не количество ветвей, а то, сколько кода идет в блоке между ними. Ветвь в любой другой строке - это плохо, но если вы можете поместить дюжину строк в блок между ветвями, вероятно, можно будет достаточно хорошо спланировать эти инструкции, чтобы ветвь не слишком ограничивала процессор или компилятор. *
Но в типичном коде ветки по существу бесплатны. В типичном коде не существует того, что много ветвей, сгруппированных близко друг к другу в критичном для производительности коде.