Почему инструкция ветвления процессора медленная?

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

Это прекрасно, хотя ни одна из статей не объяснила, почему я должен это делать. Что именно происходит, когда CPU декодирует инструкцию ветвления и решает сделать прыжок? И что такое "вещь", которая делает ее медленнее, чем другие инструкции (например, добавление)?

Ответ 1

Инструкция перехода не является по своей природе медленнее любой другой команды.

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

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

Вот почему такие вещи, как предсказание ветвей и интервалы задержки ветвления существуют.

Ответ 2

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

Так как CPU не знает, какая следующая инструкция будет выполняться при выполнении инструкции jmp, она использует методы прогнозирования ветвей для прогнозирования того, будет ли выполняться инструкция перехода или not (Например, команда перехода в фрагменте цикла, вероятно, вернет поток команд обратно в голову цикла).

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

Ответ 3

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

Подробнее о оптимизации на С++ в компиляторе Microsoft здесь. Оптимизатор, управляемый профилем, использует информацию о времени выполнения (то есть, какие части кода большинство используется) для оптимизации вашего кода. Ускорение находится в диапазоне 20%.

Одна из операций - "Условная оптимизация ветвей", например - если большую часть времени я равна 6, это быстрее:

if (i==6)
{
    //...
}

else
{
    switch (i)
    {
        case 1: //
        case 2: //
        //...
    }
}

чем:

switch (i)
{
    case 1: //
    //...
    case 6: //
    case 7: //
}

Вот сообщение в блоге по другим оптимизациям: http://bogdangavril.wordpress.com/2011/11/02/optimizating-your-native-program/