На найнижчому рівні (в апаратному забезпеченні), так, якщо s дорогі. Щоб зрозуміти, чому, ви повинні зрозуміти, як працюють трубопроводи .
Поточна інструкція, що виконується, зберігається у щось, що зазвичай називається покажчиком інструкцій (IP) або програмним лічильником (ПК); ці терміни є синонімами, але різні терміни використовуються в різних архітектурах. Для більшості інструкцій ПК наступної інструкції - це лише поточний ПК плюс довжина поточної інструкції. Для більшості архітектур RISC інструкції мають постійну довжину, тому ПК можна збільшити на постійну суму. Для архітектур CISC, таких як x86, інструкції можуть бути змінної довжини, тому логіка, яка декодує інструкцію, повинна з’ясувати, як довго поточна інструкція знаходить місце розташування наступної інструкції.
Однак для інструкцій з гілок наступна інструкція, яку потрібно виконати, не є наступним розташуванням після поточної інструкції. Гілки є гото - вони повідомляють процесору, де знаходиться наступна інструкція. Гілки можуть бути як умовними, так і безумовними, а цільове розташування може бути або фіксованим, або обчисленим.
Умовний проти безумовного легко зрозуміти - умовна гілка береться лише за умови виконання певної умови (наприклад, чи однакове число дорівнює іншому); якщо гілка не береться, контроль переходить до наступної інструкції після гілки, як звичайно. Для безумовних гілок завжди береться гілка. Умовні гілки відображаються в if
операторах та контрольних тестах for
і while
циклів. Безумовні гілки відображаються у нескінченних циклах, викликах функцій, поверненнях функцій break
та continue
операторах, сумнозвісному goto
твердженні та багатьох інших (ці списки далеко не вичерпні).
Цільова галузь - ще одне важливе питання. Більшість гілок мають фіксовану ціль гілки - вони переходять до певного місця в коді, яке фіксується під час компіляції. Сюди входять if
оператори, усілякі цикли, звичайні виклики функцій та багато іншого. Обчислені гілки обчислюють ціль гілки під час виконання. Сюди входять switch
оператори (іноді), повернення з функції, виклики віртуальних функцій та виклики покажчика на функції.
То що це все означає для продуктивності? Коли процесор бачить, що інструкція гілки з’являється в його конвеєрі, йому потрібно з’ясувати, як продовжувати заповнювати конвеєр. Для того, щоб зрозуміти, які вказівки приходять після гілки в потоці програм, їй потрібно знати дві речі: (1) чи буде взята гілка, і (2) ціль гілки. Виявлення цього називається передбаченням гілок , і це складна проблема. Якщо процесор вгадав правильно, програма продовжує працювати на повній швидкості. Якщо натомість процесор вгадав неправильно , він просто витратив деякий час на обчислення неправильної речі. Тепер він повинен промити конвеєр і перезавантажити його інструкціями з правильного шляху виконання. Підсумок: великий показник продуктивності.
Таким чином, причина того, що виписки є дорогими, пов’язана з неправильними прогнозами галузей . Це лише на найнижчому рівні. Якщо ви пишете код високого рівня, вам зовсім не потрібно турбуватися про ці деталі. Вам слід піклуватися про це, лише якщо ви пишете надзвичайно важливий для продуктивності код на мові C або в збірці. У цьому випадку написання коду без гілок часто може перевершувати код, який гілкується, навіть якщо потрібні ще кілька інструкцій. Є деякі цікаві бітові-крутив трюки , які ви можете зробити , щоб обчислити такі речі, як abs()
, min()
і max()
без розгалуження.