Reklama

Архітектура та мікроархітектура процесорів

   Під архітектурою процесора розуміється його програмна модель, тобто програмно-видимі властивості. У цій книзі розглядаються тільки процесори х86 з архітектурою IA-32 (Intel Architecture 32 bit) 6-8-го поколінь зі всіма їх мультимедійними, потоковими та 64-бітними розширеннями (AMD х86-64 і Intel ЕМ64Т). Архітектура IA-64 (процесори Itanium) у персональному них комп’ютерах не використовується і тут не розглядається.

   Основні програмно-видимі властивості процесора – це набір його регістрів, система команд (визначальна також роботу з пам’яттю) і механізм обробки переривань. Процесори х86 є явно вираженими представниками CISC-архітектури: за складністю системи команд їм немає рівних, при цьому базових архітектурних регістрів досить мало. У міру розвитку сімейства в процесори вводять все більш потужні команди, що дозволяють скорочувати число інструкцій, необхідний для вирішення одних і тих же завдань. Однак ці команди все складніше виконувати. Кількість архітектурних регістрів збільшується: з’явилися блоки ММХ, ХММ, а в 64-бітових розширеннях ще й 8 додаткових спільних регістрів.

   Під мікроархітектурою розуміється внутрішня реалізація програмної моделі. Для однієї і тієї ж архітектури IA-32 різними фірмами і в різних поколіннях застосовуються істотно розрізняються мікроархітектурние реалізації: при цьому, природно, прагнуть до максимального підвищення продуктивності (швидкості виконання програм). Починаючи з процесорів Р6 (і AMD К5), в мікроархітектурі застосовується RISC-ядро, що виконує мікрооперації (uOps), на які розкладаються складні інструкції х86. У результаті продуктивність процесора (за швидкістю виконання інструкцій х86) залежить від способу розкладання і швидкості виконання мікроінструкцій. При цьому підвищувати продуктивність можна різними способами: прискорювати виконання мікрооперацій (за рахунок підвищення тактової частоти), по можливості распараллелівать виконання мікрооперацій, скорочувати число мікрооперацій, необхідних для виконання однієї інструкції х86. У лідерів «процесоробудування» – Intel і AMD – підходи до оптимізації різняться: при порівнянній продуктивності процесори AMD працюють на більш низьких тактових частотах. Однак зауважимо, що підвищення продуктивності процесорів х86 обходиться занадто дорого (в порівнянні з «чистими» RISC-архітектурами) – вимагає дуже складних керуючих пристроїв, на які і йде значна частина транзисторів процесора і які, до того ж, виділяють значну потужність. Комп’ютери на «чистих» RISC-процесорах (наприклад, Power MAC) забезпечують ту ж прикладних продуктивність, що і IBM PC на Pentium 4, але при цьому тактова частота RISC-процесорів у кілька разів нижче частоти CISC-процесорів Pentium 4.

   Пояснимо основні поняття, пов’язані з конвеєризації і розпаралелюванню виконання інструкцій (точніше, мікрооперацій).

   Конвейеризация (pipelining) передбачає, що кожна інструкція обробляється за кілька етапів, причому кожен етап виконується на своїй ступені конвеєра процесора. При виконанні інструкція просувається по конвеєру в міру звільнення наступних ступенів. Таким чином, на конвеєрі одночасно може оброблятися декілька послідовних інструкцій.

   У сучасних процесорах паралельно можуть працювати кілька конвеєрів, так що продуктивність процесора можна оцінювати темпом виходу виконаних інструкцій з усіх його конвеєрів. Для досягнення максимальної продуктивності процесора – забезпечення повного завантаження конвеєрів – програма повинна складатися з урахуванням мікроархітектурних особливостей процесора. Звичайно, і код, згенерований звичайним способом, буде виконуватися на більш нових процесорах досить швидко (за рахунок більш високої тактової частоти). Проте ряд програм на процесорах Pentium III працює швидше, ніж на Pentium 4, при однакових тактових частотах: наддовгий конвеєр Pentium 4 на «поворотах» непередбачувано розгалужених програм «заносить», що призводить до його простоїв. Конвеєр «класичного» процесора Pentium має п’ять щаблів. Конвеєри процесорів Р6 з суперконвейерною архітектурою (superpipelined) мають більше число ступенів (10-12), що дозволяє спростити кожну з них і, отже, скоротити час перебування в них інструкцій. Гіперконвейер Pentium 4 має вже 20 ступенів для повторно виконуваних ділянок програмного коду (з кеша трас), а якщо його вважати повну довжину (починаючи з декодування), то набереться близько 30 ступенів. 

   Скалярним називають процесор з єдиним конвеєром, до цього типу від носяться всі процесори Intel до класу 486 включно. Суперскалярний (superscalar) процесор має більше одного конвеєра (Pentium – два); ці конвеєри здатні обробляти інструкції паралельно.

   Інструкції переходів і особливо розгалужень порушують безперервність роботи початкових ступенів конвеєра, оскільки вони повинні починати вибірку і декодування інструкцій з нового, заздалегідь невідомої адреси. Передбачення переходів (branch prediction) дозволяє продовжувати вибірку і декодування потоку інструкцій після вибірки інструкції розгалуження (умовного переходу), не чекаючи перевірки самого умови. У процесорах колишніх поколінь інструкція переходу припиняла конвеєр (вибірку інструкцій) до виконання власне переходу, на чому, природно, губилася продуктивність. Передбачення переходів спрямовує потік вибірки й декодування по одній з гілок, при цьому використовується ряд методів передбачення:

1.             При статичному пророкуванні (схема закладена в процесор) переходи з одним умовам, найімовірніше, відбудуться, а за іншими – ні. Переходи тому швидше відбудуться (це типовий цикл), вперед – ні (типово для обробки помилок).

2.             Динамічне передбачення спирається на передісторію обчислювального процесу – для кожної конкретної команди переходу (її адреси в пам’яті) накопичується статистика поведінки, на основі якої передбачається перехід. Для динамічного передбачення в процесор вводять таблицю ВТВ (Branch Table Buffer – буфер таблиці переходів), що нагадує кеш з асоціативним пошуком.

3.             Програмні «натяки» (hints) – нові префікси інструкцій (з’явилися у Р4), що перекривають статичне пророцтво. Натяки закладаються в програмний код на етапі компіляції. 

   Конвейеризация в процесорах х86 ускладнюється архітектурними особливостями: великим розкидом інструкцій по складності і, відповідно, за часом виконання. Для підвищення продуктивності ті сходи конвеєра, на яких проводиться найбільш складна робота, намагаються распараллелівать. При цьому в процесор вводиться велика кількість виконавчих елементів, які можуть одночасно обробляти різні інструкції (або різні частини однієї складної інструкції, розбитою на декілька більш простих).

   Для того щоб процесор міг паралельно обробляти декілька інструкцій, програмний код повинен бути написаний (скомпільований) так, щоб у «поле зору» процесора (тобто на його конвеєрі) виявлялося побільше фактично незалежних один від одного інструкцій. У процесорах RISC-архітектур, як правило, багато універсальних регістрів, що має в своєму розпорядженні до написання коду, зручного для паралельного виконання. Мале число і нерівноправність основних регістрів х86 не мають до програмування з урахуванням паралельності виконання. Проте якщо кілька інструкцій, що звертаються до одного й того ж регістру, не мають фактичних залежностей за даними (не використовують результати один одного), їх можна виконувати одночасно в різних фізичних регістрах процесора (архітектурно невидимих), яких може бути багато. Це робиться шляхом перейменування регістрів (register renaming) – тимчасового зіставлення фізичних регістрів логічним з відображенням правильної послідовності зміни складаний архітектурних (логічних) регістрів.

   Просування даних (data forwarding) має на увазі початок виконання інструкції до готовності всіх операндів. При цьому виконуються всі можливі дії, і декодувати інструкція з одним операндом поміщається в виконавчий пристрій, де чекає готовності другого операнда, що виходить з іншого виконавчого пристрою.

   При виконанні за припущенням, званому також спекулятивним (speculative execution), використовується результат передбачень переходів: інструкції з передвіщеної гілки переходу не тільки декодуються, але і по можливості виконуються до перевірки умови переходу. Якщо пророцтво збувається, то праця виявляється не марним, якщо не збувається, доводиться виконувати відкат – в цьому випадку конвеєр виявляється недовантаженим і простоює кілька тактів (як мінімум стільки, скільки ступенів біля конвеєра).

   Виконання зі зміною послідовності інструкцій (out-of-order execution), властиве RISC-архітектурі, тепер реалізується і для процесорів х86. При цьому змінюється порядок внутрішніх маніпуляцій даними, а зовнішні (шинні) операції введення-виведення і запису в пам’ять виконуються, звичайно ж, в порядку, встановленому програмним кодом. Однак ця здатність процесора найбільшою мірою може блокуватися недосконалістю програмного коду (особливо 16-бітних додатків), якщо він генерується без урахування можливості зміни порядку виконання інструкцій.

   Описані терміни та технології вкладаються у загальне поняття «динамічного виконання» (dynamic execution), введене фірмою Intel з появою процесорів Р6. Поліпшене динамічне виконання (enhanced dynamic execution) відрізняється поліпшеннями різних сторін, зокрема, поліпшенням передбачень переходів.

   Завдяки ускладнення мікроархітектури від покоління до покоління зростає продуктивність процесорів, причому це зростання забезпечується двома факторами. По-перше, зростає тактова частота ядра. По-друге, збільшується відносний темп виконання інструкцій. Так, в середньому процесори 1 -, 2 -, 3 -, 4 -, 5 -, 6 – і 7-го поколінь завершують чергову посібник з інтервалом 12, 5, 4, 2, 1, 1 / 2 і 1 / 3 тактів . Півтакта і третина такту на інструкцію – звучить, звичайно, дивно. Але якщо згадати про 8-байтной шині даних, що дозволяє за один такт завантажити фрагмент коду, що містить кілька команд, і про кількох виконавчих пристроях, одночасно приступають до їх виконання, то питання розсіюються. Звичайно ж, час, потрібний для повного проходження інструкції від її вибірки до виконання, вимірюється десятками тактів (і зростає з подовженням конвеєра). 

Reklama