Багатоядерний процесор. Що таке ядро ​​процесора

Багатоядерний процесор - це центральний мікропроцесор, що містить 2 і більше обчислювальних ядра на одному процесорному кристалі або в одному корпусі.

Перший (природно, одноядерний!) мікропроцесор Intel 4004 був представлений 15 листопада 1971 Корпорацією Intel. Він містив 2300 транзисторів, працював на тактовій частоті 108 кГц та коштував $300.

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

Тривалий час підвищення продуктивності традиційних одноядерних процесорівпереважно відбувалося з допомогою послідовного збільшення тактової частоти (близько 80% продуктивності процесора визначала саме тактова частота) з одночасним збільшенням кількості транзисторів однією кристалі. Однак подальше підвищення тактової частоти (при тактовій частоті більше 3,8 ГГц чіпи просто перегріваються!) упирається в низку фундаментальних фізичних бар'єрів (оскільки технологічний процесмайже впритул наблизився до розмірів атома: сьогодні процесори випускаються за 45-нм технологією, а розміри атома кремнію - приблизно 0,543 нм):

* По-перше, зі зменшенням розмірів кристала і з підвищенням тактової частоти зростає струм витоку транзисторів. Це веде до підвищення споживаної потужності та збільшення викиду тепла;

* По-друге, переваги вищої тактової частоти частково зводяться нанівець через затримки при зверненні до пам'яті, так як час доступу до пам'яті не відповідає зростаючим тактовим частотам;

* по-третє, для деяких додатків традиційні послідовні архітектури стають неефективними зі зростанням тактової частоти через так зване «фон-нейманівське вузьке місце» - обмеження продуктивності в результаті послідовного потоку обчислень. При цьому зростають резистивно-ємні затримки передачі сигналів, що є додатковим вузьким місцем, пов'язаним з підвищенням тактової частоти.

Застосування багатопроцесорних систем також набуло широкого поширення, оскільки вимагає складних і дорогих багатопроцесорних материнських плат. Тому було вирішено вимагати подальшого підвищення продуктивності мікропроцесорів іншими засобами. Найефективнішим напрямом була визнана концепція багатопоточності, що зародилася у світі суперкомп'ютерів, - це паралельна паралельна обробка декількох потоків команд.

Так у компанії Intelнародилася Hyper-Threading Technology (HTT) – технологія надпоточної обробки даних, яка дозволяє процесору виконувати в одноядерному процесорі паралельно до чотирьох програмних потоків одночасно. Hyper-threading значно підвищує ефективність виконання ресурсомістких додатків (наприклад, пов'язаних з аудіо- та відеоредагуванням, 3D-моделюванням), а також роботу ОС у багатозадачному режимі.

Процесор Pentium 4 із включеним Hyper-threading має одне фізичне ядро, яке розділене на два логічні, тому операційна система визначає його, як два різні процесори (замість одного).

Hyper-threading фактично стала трампліном до створення процесорів із двома фізичними ядрами на одному кристалі. У 2-ядерному чіпі паралельно працюють два ядра (два процесори!), які при меншій тактовій частоті забезпечують більшу продуктивність, оскільки паралельно (одночасно!) виконуються два незалежні потоки інструкцій.

Здатність процесора виконувати одночасно кілька програмних потоків називається паралелізмом на рівні потоків (TLP - thread-level parallelism). Необхідність TLP залежить від конкретної ситуації (у деяких випадках вона просто марна!).

Одним з етапів удосконалення архітектури фон Неймана є розпаралелювання потоків. Thread Level Parallelism, TLP). Розрізняють одночасну багатопоточність (Simultaneous Multithreading, SMT) та багатопоточність на рівні кристала (Chip- level Multithreading, CMT). Ці два підходи переважно різняться уявленням у тому, що таке потік. Типовим представником SMTє так звана технологія HTT (Hyper- Threading Technology).

П ервими представниками архітектури CMPстали процесори, призначені для використання у серверах. Це був простий тандем, у таких приладах на одній підкладці розміщувалися два, по суті, незалежні ядра (Рис.8,). Розвитком цієї схеми спочатку стала структура із загальною кеш – пам'яттю рис. 9, а потім структура з багатопоточністю в кожному ядрі.

Переваги багатоядерних процесорів полягають у наступному.

    Простота (природно відносна) проектування та виробництва. Розробивши одне ефективне ядро, його можна тиражувати у кристалі, доповнюючи архітектуру необхідними системними компонентами.

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

У цілому ж, якщо уважно подивитися на малюнки 8 і 9, можна побачити, що принципової різниці між, скажімо, 2-х процесорною системою та ЕОМ на 2-х ядерному процесорі немає. Проблеми однакові. І одна з перших – відповідна операційна система.

Способи організації роботи процесорів

Головним стимулом розвитку архітектури ЕОМ є підвищення продуктивності. Один із способів підвищення продуктивності ЕОМ - спеціалізація (як окремих елементів ЕОМ, так і створення спеціалізованих обчислювальних систем).

Спеціалізація процесорів почалася з 60-х років, коли центральний процесор великих ЕОМ був звільнений від виконання рутинної операції із введення-виведення інформації. Ця функція була передана процесору введення-виводу, що здійснює зв'язок з периферійними пристроями.

Інший шлях підвищення продуктивності – відхід від послідовної архітектури фон Неймана, орієнтація на паралелізм. М. Флін звернув увагу, що є лише дві причини, породжують обчислювальний паралелізм - незалежність потоків команд, одночасно існуючих у системі, і незв'язаність даних, оброблюваних одному потоці команд. Якщо перша причина паралелізму обчислювального процесу досить відома (це простий мультипроцесування), то на паралелізмі даних зупинимося докладніше, оскільки в більшості випадків він існує приховано від програмістів і використовується обмеженим колом професіоналів.

Найпростішим прикладом паралелізму даних є послідовність двох команд: А=В+С; D=E*F;

Якщо суворо дотримуватися принципу фон Неймана, друга операція може бути запущена на виконання тільки після завершення першої операції. Однак очевидно, що порядок виконання цих команд не має жодного значення - операнди А, В та С першої команди ніяк не пов'язані з операндами D, Е та F другої команди. Іншими словами, обидві операції є паралельними саме тому, що операнди цих команд не пов'язані між собою. Можна навести безліч прикладів послідовності з трьох і більше команд з незв'язаними даними, які призведуть до однозначного висновку: практично будь-яка програма містить групи операцій над паралельними даними.

Д Інший вид паралелізму даних, як правило, виникає в циклічних програмах обробки масивів даних. Наприклад, при додаванні елементів двох масивів одна команда може обробляти великий масив (множинний потік) даних. Подібні команди називаються векторними, а процесор, який реалізує такий режим, – векторним. Можна дати таке визначення: «Векторний процесор - процесор, який би паралельне виконання операції над масивами даних (векторами). Він характеризується спеціальною архітектурою, побудованою на групі паралельно працюючих процесорних елементів, і призначений для обробки зображень, матриць та масивів даних».

Існує кілька досить близьких за змістом класифікацій програмного паралелізму, з яких найбільш визнаною вважається класифікація за шістьма рівнями (Рис.10). Три верхніх рівня паралелізму займають великі програмні об'єкти - незалежні завдання, програми та процедури програми. Незв'язані оператори, цикли та операції утворюють нижні рівні паралелізму. Якщо поєднати таке ранжування з категоріями М. Фліна "паралельні потоки команд" і "паралельні потоки даних", то видно, що паралелізм верхнього рівня в основному досягається за рахунок безлічі незалежних потоків команд, а паралелізм нижнього рівня зобов'язаний своїм існуванням головним чином незв'язаним потокам даних .

Конвеєрна обробка та конвеєрні структури

Про днем з ефективних способівПідвищення продуктивності ЕОМ є конвеєризація. На рис. 11 а)показана обробка в одиночному універсальному блоці, а на рис.11 б)і в)- У конвеєрі. Ідея конвеєрної обробки полягає у розбиття функції, що реалізується універсальним функціональним блоком (ФБ), між декількома, спеціалізованими. Всі функціональні блоки конвеєра повинні працювати з однаковою швидкістю (хоча б у середньому). Насправді останнього домогтися вдається рідко як наслідок, продуктивність конвеєра знижується, оскільки період надходження вхідних даних визначається максимальним часом їх обробки у кожному функціональному блоці. Для компенсації флуктуацій часу роботи ФБ з-поміж них включають буферні регістри. Більш універсальним прийомом є включення буферних пристроїв типу FIFO (рис 11 в). Слід звернути увагу на ще одну різницю між малюнками б)і в). У структурі в)відсутня лінія синхронізації СІ. Це не означає, що її не може бути в подібній структурі, просто існує два типи конвеєрів: синхроннііз загальною лінією синхронізації та асинхронні, без такої. Перші ще називають з керуванням командами, а другі – з керуванням даними. Прикладом асинхронних конвеєрів можуть бути систолічні масиви.

До онвеєр не завжди є лінійним ланцюжком блоків. Іноді виявляється вигідним, функціональні блоки з'єднають між собою не послідовно, а за складнішою схемою відповідно до логіки обробки, при цьому одні блоки в ланцюжку можуть пропускатися, а інші - утворювати циклічні структури. Структура нелінійного конвеєра, здатного обчислювати дві функції X та Y, та діаграми, в якій функціями X та Y потрібні ті чи інші функціональні блоки наведено на рис. 12

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

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

Що стосується AMP, розробник системи визначає, як організувати поділ апаратних ресурсів, використовуваних програмами, між процесорами. Зазвичай, подібне виділення ресурсів здійснюється статично під час завантаження і включає розподіл фізичної пам'яті, ініціалізацію переферії та обробку переривань Хоча система може виділяти ресурси динамічно, використання такого підходу може спричинити ускладнення координації між процесорами.

В AMP системах процеси завжди виконуються на тому самому процесорі, навіть якщо інший процесор вільний (виконується idle). Як результат, один із процесорів може бути не навантажений або перевантажений. Щоб вирішити цю проблему, система може дозволити програмам динамічно мігрувати з одного процесора на інший, однак, така поведінка може викликати ускладнення ведення контрольних точок з інформацією про стан або ускладнити сервісне переривання, яке призводить до припинення виконання програми на одному процесорі та його запуску на іншому . Такі міграції складні або навіть неможливі, коли процесори виконують різні ОС.

Симетрична багатопроцесорність Розподіл ресурсів під час проектування багатоядерної системи може бути складним завданням, особливо, якщо різні програмні компоненти не знають, як інші компоненти використовують ці ресурси.

Симетрична багатопроцесорність (SMP) вирішує цю проблему, дозволяючи виконувати одну копію Neutrino на всіх процесорах системи. ОС взаємодіє з усіма елементами системи, що дозволяє розподіляти ресурси між декількома процесорами чи взагалі без втручання з боку розробника. Крім того, Neutrino надає вбудований механізм стандартизованих примітивів, таких як: pthread_mutex_lock(), pthread_mutex_unlock(), pthread_spin_lock(), and pthread_spin_unlock(), які дозволяють декількома програмами просто і безпечно розділяти ресурси.

Виконання однієї операційної системи на декількох процесорах дозволяє SMP динамічно виділяти ресурси певним додатком, а не процесорам, таким чином розширюючи використання наявної обчислювальної потужності. Також, це дозволяє системним інструментамтрасування вести збір оперативної статистики та даних про взаємодію додатків у багатопроцесорній системі, що дає розробнику цінну інформацію про те, як оптимізувати та налагоджувати додатки.

Наприклад, системний профільник (System Profiler), що входить до складу IDE, може відслідковувати міграцію потоків з одного процесора на інший, як і системні виклики, події планування, передачу повідомлень між додатками та інші події, і все це з великою частотою тимчасових міток. Синхронізація програм також спрощується завдяки можливості використання стандартних примітивів операційної системи, а не складних механізмів IPC.

Neutrino дозволяє потокам програми виконуватись паралельно на будь-якому процесорі, роблячи доступною програмаму будь-який час всю наявну обчислювальну потужність багатоядерної системи. Витіснення і можливості пріоритетів потоків дозволяють розробнику бути впевненим, що процесорний час буде передано додатку, яке потребує його найбільше.

Мікроядро Neutrino у наближенні Симетрична багатопроцесорна обробка (Symmetrical Multi-Processing, SMP) зазвичай асоціюється з новітніми операційними системами (наприклад, UNIX і NT), встановленими високопродуктивні сервери. Такі великі, монолітні системи, як правило, мають дуже складну архітектуру і є результатом безлічі людино-годин, витрачених на розробку. Оскільки ядро ​​з такою великою архітектурою несе практично всі служби операційної системи, для забезпечення симетричної багатопроцесорності в ньому потрібно зробити величезні зміни, які зазвичай тягнуть за собою необхідність внести в код велику кількість модифікацій і використовувати спеціальні блокування активного очікування (spinlocks).

ОС QNX Neutrino, навпаки, містить у собі компактне мікроядро, яке оточене процесами, що діють як адміністратори ресурсів і забезпечують такі служби, як файлові системи, символьне введення/виведення, мережна взаємодія. За рахунок модифікації мікроядра можна забезпечити SMP-функції для всіх служб ОСбез зміни програмного коду . Якщо процеси, що реалізують ці служби, є багатопотоковими, всі ці потоки можна розподілити між кількома процесорами. Більш того, навіть однопотоковий серверний процес може бути більш ефективно реалізований завдяки симетричній багатопроцесорності, оскільки цей потік можна запланувати на виконання наявними процесорами разом з іншими серверними та клієнтськими процесами.

Дійсно, відповідно до описаного раніше підходу, для реалізації можливостей симетричної багатопроцесорності в ядрі/адміністраторі процесів ОС QNX Neutrino використовується лише кілька кілобайт програмного коду. Версії адміністратора процесів за допомогою симетричної багатопроцесорності існують для наступних основних сімейств процесорів:

    PowerPC (наприклад , procnto-600-smp );

    MIPS ( procnto-smp );

    x86 ( procnto-smp ).

Версія для платформи x86 може також використовуватися і для будь-якої іншої системи, яка відповідає специфікації Intel MultiProcessor Specification (MP Spec) та містить до восьми процесорів Pentium (або більш продуктивних, ніж Pentium). Крім того, ОС QNX Neutrino підтримує нову технологію багатопотокової обробки фірми Intel (Hyper-Threading Technology), яка застосовується у процесорах P4 та Xeon.

Адміністратор procnto-smp , звичайно, працює і на однопроцесорних системах, які не мають можливостей паралельних обчислень. Таким чином, якщо двопроцесорна материнська плата Pentium багато в чому аналогічна однопроцессорной, вона стає дуже вигідним рішенням, оскільки таку материнську плату можна легко масштабувати за допомогою простого додавання ще одного процесора. Завдяки тому, що реалізація симетричної багатопроцесорності досягається в ОС QNX Neutrino лише кількома додатковими кілобайтами, вона може легко застосовуватися в системах, що вбудовуються, навіть з обмеженими обчислювальними ресурсами, а не тільки на високопродуктивних серверах.

Версії SMP-ядра для сімей мікропроцесорів PowerPC і MIPS забезпечують повну підтримку багатопроцесорності на відповідному устаткуванні (у тому числі синхронізацію кеша, міжпроцесорні переривання тощо). Версія SMP-ядра для PowerPC підтримує будь-які системи із процесорами серії 7ххабо 74 хх (наприклад, на таких платформах, як Motorola MVP або Marvell EV-64260-2XMPC7450 SMP Development System). Версія SMP-ядра для MIPS підтримує такі системи як процесор з подвійним ядром Broadcom BCM1250.

x 86 Мікроядро ОС QNX Neutrino містить дуже невеликий обсяг програмного коду, пов'язаного з апаратною стороною системи. Програмний код, який визначає можливості системи, є в програмі, що активізується при запуску системи і призначеної для системної ініціалізації, визначення доступних ресурсів пам'яті і т. д. Зібрана інформація міститься в таблицю пам'яті, що використовується (тільки для читання) мікроядром і всіма процесами.

Програма startup-bios призначений для роботи на системах, сумісних зі специфікацією Intel MP Spec (версії 1.4 або вище). Ця програмазапуску виконує такі функції:

  • ініціалізація кожного додаткового процесора.
Після скидання системи код перезапуску виконує лише один процесор. Цей процесор називаєтьсязавантажувальним процесором (Boot Processor, BP). Для кожного виявленого додаткового процесора завантажувальний процесор, на якому виконується програма, що запускає startup-bios , виконуватиме такі дії:

    ініціалізувати процесор;

    перемикати його в захищений 32-бітовий режим;

    виділяти йому власну таблицю сторінок;

Завантаження багатопроцесорної системи на основі архітектури PowerPC або MIPS У багатопроцесорних системах на основі архітектури PowerPC або MIPS послідовність завантажувальних дій аналогічна до тієї, яка застосовується в архітектурі x86, але відмінність полягає в тому, що в них використовується спеціальна завантажувальна програма(наприклад, startup-mvp або startup-bcm1250 ). Зокрема, програма початкового завантаження в архітектурі PowerPC призначена для виконання наступних функцій:

    визначення кількості наявних процесорів;

    ініціалізація кожного додаткового процесора;

    ініціалізація контролерів переривань (IRQ) та міжпроцесорних переривань (IPI), системного контролера тощо.

Для кожного виявленого додаткового процесора програма, що запускає, буде виконувати наступні дії:

    ініціалізувати процесор;

    ініціалізувати блок керування пам'яттю (блок MMU);

    ініціалізувати кеші;

    переводити процесор у режим із забороненими перериваннями в очікуванні, поки ядро ​​не звільнить його.

Як працює мікроядро із симетричною багатопроцесорністю Після того як додаткові процесори звільнено і запущено, всі процесори вважаються рівноправними з точки зору планування потоків. Планування Алгоритм планування застосовується відповідно до тих самих правил, що діють в однопроцесорних системах. Це означає, що потік із найвищим пріоритетом виконуватиметься на вільному процесорі. Якщо виникає інший потік, готовий до виконання з найвищим пріоритетом, він буде переданий відповідному процесору. Якщо цільового вказується більше одного процесора, тоді мікроядро спробує відправити потік на той процесор, на якому він виконувався в останній раз. Такий механізм прив'язки (affinity) використовується для того, щоб зменшити міграцію потоків між процесами, що знижує продуктивність роботи кешів.

У SMP-системі планувальник може самостійно керувати плануваннямнизькопріоритетних потоків для того, щоб оптимізувати використання кешів та мінімізувати міграцію потоків між процесами. У будь-якому випадку, ті правила планування в реальному часі, що застосовуються на однопроцесорних системах, повною мірою застосовні і багатопроцесорних системах.

Блокування ядра В однопроцесорній системі кожен момент часу в мікроядрі може виконуватися тільки один потік. Більшість операцій, що виконуються ядром, мають дуже невелику тривалість (зазвичай, трохи більше кількох мікросекунд на процесорі класу Pentium). Мікроядро в ОС QNX Neutrino розроблено таким чином, щоб забезпечити можливість повного витіснення і перезапуску для тих операцій, які вимагають більшого часу. Така архітектура робить мікроядро дуже компактним та швидкодіючим і не вимагає застосування великої кількості детально розроблених блокувань. Цікаво відзначити, що використання множини блокувань в основному коді ядра помітно знижує його швидкодію, адже кожне блокування, як правило, вимагає звернення до процесорної шини, а це може призводити до зупинення процесора.

У SMP-системах ОС QNX Neutrino відповідає тій же філософії: у ядрі, що витісняється і перезапускається, повинен знаходитися тільки один потік. Мікроядро є доступним для будь-якого процесора, але тільки один з них може отримати доступ до нього в кожний момент часу.

У більшості систем час, що витрачається на виконання коду мікроядра, становить лише невелику частку загального обчислювального навантаження на процесор. Тому виникнення конфліктів стає швидше винятком, ніж правилом. Це особливо відноситься до мікроядру, в якому традиційні служби операційної системи (наприклад, файлові системи), являють собою окремі процеси і не є частиною самого ядра.

Міжпроцесорні переривання Процесори взаємодіють між собою у вигляді міжпроцесорних переривань (Inter-Processor Interrupt, IPI). Міжпроцесорні переривання дозволяють ефективно здійснювати планування та управління потоками на безлічі процесорів. Наприклад, міжпроцесорне переривання часто потрібне в ситуаціях, коли:

    потік з вищим пріоритетом перетворюється на стан готовності;

    потік, який виконується на іншому процесорі, отримує сигнал;

    потік, який виконується на іншому процесорі, завершується (canceled);

    потік, який виконується на іншому процесорі, знищується.

Критичні секції програмного коду Для управління доступом до структур даних, що розділяються, потоки і процеси використовують такі стандартні POSIX-примітиви, як мутекси, умовні змінні і семафори. Всі ці примітиви однаково працюють як на однопроцесорних, так і багатопроцесорних системах.

У багатьох системах реального часу часто виникає необхідність забезпечити захист доступу до структур даних між обробником переривань і потоком, що володіє цим обробником. Традиційні примітиви POSIX, що використовуються між потоками, не можуть застосовуватися обробником переривань. Існує два вирішення цієї проблеми.

    Зняти всю роботу з обробника переривань та перенести її на рівень потоку. Завдяки високій швидкості планування потоків в ОС QNX Neutrino це рішення може бути дуже ефективним.

    В однопроцесорній системі під керуванням ОС QNX Neutrino обробник переривань може витісняти потоки, але потоки ніколи не можуть витісняти обробник переривань. Потік може захищати себе від витіснення обробником переривань за допомогою заборони або дозволу переривань надуже короткі періоди часу.

Захист потоку в однопроцесорній системі можна реалізувати за допомогою програмного коду у такій формі:

Були об'єднані кілька напівпровідникових кристалів, то конструкцію називають багаточиповий модуль(Англ. multi-chip module, MCM).

Терміном багатопроцесорнийпозначають комп'ютери, що мають кілька фізично роздільних процесорів (наприклад, серверні материнські плати часто мають 2 або 4 сокети для підключення декількох чіпів), але керовані одним екземпляром ОС.

Мультипроцесор на кристалі(Single-chip multiprocessor, on-chip multiprocessor, chip multiprocessing, CMP) - так ранні дослідники називали свої проекти розміщення кількох процесорів однією підкладці .

Архітектура багатоядерних систем

Продуктивність

У додатках, оптимізованих під багатопоточність, спостерігається приріст продуктивності на багатоядерному процесорі. Однак, якщо програма не оптимізована, то вона не отримуватиме практично ніякої вигоди від додаткових ядер, а може навіть виконуватися повільніше, ніж на процесорі з меншою кількістю ядер, але більшою тактовою частотою. Це в основному програми, розроблені до появи багатоядерних процесорів, або додатки, які в принципі не використовують багатопоточність.

У серпні 2011 року компанією AMD було випущено перші 16-ядерні серійні серверні процесори Opteron серії 6200 (кодове найменування Interlagos). Процесор Interlagosоб'єднує в одному корпусі два 8-ядерні (4-модульні) чіпи і є повністю сумісним з існуючою платформою AMD Opteron серії 6100 (Socket G34).

  • Tutorial

У цій статті я спробую описати термінологію, яка використовується для опису систем, здатних виконувати кілька програм паралельно, тобто багатоядерних, багатопроцесорних, багатопотокових. Різні видипаралелізму в ЦПУ IA-32 з'являлися в різний час і в дещо непослідовному порядку. У всьому цьому досить легко заплутатися, особливо з огляду на те, що операційні системи дбайливо ховають деталі від не дуже досвідчених прикладних програм.

Мета статті - показати, що при всьому різноманітті можливих змін багатопроцесорних, багатоядерних і багатопотокових систем для програм, що виконуються на них, створюються можливості як для абстракції (ігнорування відмінностей), так і для обліку специфіки (можливість програмно дізнатися про конфігурацію).

Попередження про знаки ®, ™ у статті

Мій пояснює, чому співробітники компаній мають у публічних комунікаціях використовувати знаки авторського права. У цій статті їх довелося використати досить часто.

Процесор

Звичайно, найдавніший, найчастіше використовуваний і неоднозначний термін - це «процесор».

В сучасному світіпроцесор - це те (package), що ми купуємо у красивій Retail коробці або не дуже гарному OEM-пакетиці. Неподільна сутність, що вставляється в роз'єм (socket) на материнської плати. Навіть якщо ніякого роз'єму немає і зняти його не можна, тобто якщо він припаяний намертво, це один чіп.

Мобільні системи (телефони, планшети, ноутбуки) та більшість десктопів мають один процесор. Робочі станції та сервери іноді можуть похвалитися двома або більше процесорами на одній материнській платі.

Підтримка кількох центральних процесорівв одній системі потребує численних змін у її дизайні. Як мінімум, необхідно забезпечити їх фізичне підключення(передбачити кілька сокетів на материнській платі), вирішити питання ідентифікації процесорів (див. далі в цій статті, а також мою замітку), погодження доступів до пам'яті та доставки переривань (контролер переривань повинен уміти маршрутизувати переривання на кілька процесорів) і, звичайно ж, підтримки з боку операційної системи Я, на жаль, не зміг знайти документальної згадки моменту створення першої багатопроцесорної системи на процесорах Intel, проте Вікіпедія стверджує, що Sequent Computer Systems постачала їх вже в 1987 році, використовуючи процесори Intel 80386. Широко поширена підтримка ж декількох чіпів в одній системі стає доступною , починаючи з Intel Pentium.

Якщо процесорів кілька, кожен із них має власний роз'єм на платі. У кожного з них є повні незалежні копії всіх ресурсів, таких як регістри, що виконують пристрої, кеші. Ділять вони спільну пам'ять – RAM. Пам'ять може підключатися до них у різний спосіб і досить нетривіальними способами, але це окрема історія, що виходить за рамки цієї статті. Важливо те, що при будь-якому розкладі для програм, що виконуються, повинна створюватися ілюзія однорідної загальної пам'яті, доступної з усіх процесорів, що входять до системи.



До зльоту готовий! Intel® Desktop Board D5400XS

Ядро

Історично багатоядерність у Intel IA-32 з'явилася пізніше за Intel® HyperThreading, проте в логічній ієрархії вона йде наступною.

Здавалося б, якщо в системі більше процесорів, то вища її продуктивність (на задачах, здатних задіяти всі ресурси). Проте, якщо вартість комунікацій між ними надто велика, весь виграш від паралелізму вбивається тривалими затримками на передачу загальних даних. Саме це спостерігається у багатопроцесорних системах – як фізично, так і логічно вони знаходяться дуже далеко один від одного. Для ефективної комунікації за таких умов доводиться вигадувати спеціалізовані шини, такі як Intel QuickPath Interconnect. Енергоспоживання, розміри та ціна кінцевого рішення, звичайно, від цього не знижуються. На допомогу повинна прийти висока інтеграція компонентів - схеми, що виконують частини паралельної програми, треба підтягти ближче один до одного, бажано на один кристал. Іншими словами, в одному процесорі слід організувати декілька ядер, у всьому ідентичних один одному, але працюючих незалежно.

Перші багатоядерні процесори IA-32 від Intel були представлені у 2005 році. З того часу середня кількість ядер у серверних, десктопних, а нині й мобільних платформах невпинно зростає.

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



Мікрознімок чотириядерного процесора Intelз кодовим ім'ям Nehalem. Виділено окремі ядра, загальний кеш третього рівня, а також лінки QPI до інших процесорів та загальний контролер пам'яті.

Гіперпотік

До приблизно 2002 єдиний спосіб отримати систему IA-32, здатну паралельно виконувати дві або більше програми, полягав у використанні саме багатопроцесорних систем. У Intel Pentium 4, а також лінійці Xeon з кодовим ім'ям Foster (Netburst) була представлена ​​нова технологія - гіпертреди або гіперпотоки, - Intel HyperThreading (далі HT).

Ніщо не нове під місяцем. HT - це окремий випадок те, що у літературі називається одночасної многопоточностью (simultaneous multithreading, SMT). На відміну від «справжніх» ядер, що є повними та незалежними копіями, у разі HT в одному процесорі дублюється лише частина внутрішніх вузлів, що насамперед відповідають за зберігання архітектурного стану – регістри. Виконавчі вузли, відповідальні за організацію та обробку даних, залишаються в однині, і в будь-який момент часу використовуються максимум одним з потоків. Як і ядра, гіперпотоки ділять між собою кеші, проте починаючи з якого рівня – це залежить від конкретної системи.

Я не намагатимуся пояснити всі плюси та мінуси дизайнів з SMT взагалі і з HT зокрема. Читач, що цікавиться, може знайти досить докладне обговорення технології в багатьох джерелах, і, звичайно ж, у Вікіпедії. Однак зазначу наступний важливий момент, що пояснює поточні обмеження на кількість гіперпотоків у реальній продукції.

Обмеження потоків
У яких випадках наявність «нечесної» багатоядерності як HT виправдано? Якщо один потік програми не в змозі завантажити всі виконуючі вузли всередині ядра, їх можна «позичити» іншому потоку. Це типово для додатків, що мають «вузьке місце» не в обчисленнях, а при доступі до даних, тобто часто генерують промахи кешу і змушені чекати на доставку даних з пам'яті. У цей час ядро ​​без HT буде змушене простоювати. Наявність же HT дозволяє швидко переключити вільні виконуючі вузли до іншого архітектурного стану (т.к. воно дублюється) і виконувати його інструкції. Це - окремий випадок прийому під назвою latency hiding, коли одна тривала операція, протягом якої корисні ресурси простоюють, маскується паралельним виконанням інших завдань. Якщо програма вже має високий рівень утилізації ресурсів ядра, наявність гіперпотоків не дозволить отримати прискорення - тут потрібні «чесні» ядра.

Типові сценарії роботи десктопних та серверних програм, розрахованих на машинні архітектури загального призначення, мають потенціал до паралелізму, що реалізується за допомогою HT. Однак цей потенціал швидко «витрачається». Можливо, з цієї причини майже на всіх процесорах IA-32 кількість апаратних гіперпотоків не перевищує двох. На типових сценаріях виграш від використання трьох і більше гіперпотоків був би невеликий, а ось програш у розмірі кристала, його енергоспоживання та вартості значний.

Інша ситуація спостерігається на типових завданнях, які виконуються на відеоприскорювачах. Тому для цих архітектур характерне використання техніки SMT з більшим числом потоків. Оскільки співпроцесори Intel Xeon Phi (представлені в 2010 році) ідеологічно і генеалогічно досить близькі до відеокарт, на них може бути чотиригіперпотоку на кожному ядрі – унікальна для IA-32 конфігурація.

Логічний процесор

З трьох описаних «рівнів» паралелізму (процесори, ядра, гіперпотоки) в конкретній системі можуть бути відсутні або навіть усі. На це впливають налаштування BIOS(багатоядерність і багатопоточність відключаються незалежно), особливості мікроархітектури (наприклад, HT був відсутній в Intel Core Duo, але був повернутий з випуском Nehalem) і події при роботі системи (багатопроцесорні сервери можуть вимикати процесори, що відмовили у разі виявлення несправностей і продовжувати «летіти» на решту). Як цей багаторівневий зоопарк паралелізму видно операційній системі і, в кінцевому рахунку, прикладним додаткам?

Далі для зручності позначимо кількості процесорів, ядер та потоків у деякій системі трійкою ( x, y, z), де x- Це число процесорів, y- число ядер у кожному процесорі, а z- Число гіперпотоків у кожному ядрі. Далі я називатиму цю трійку топологією- усталений термін, що мало що має з розділом математики. твір, добуток p = xyzвизначає число сутностей, іменованих логічними процесорамисистеми. Воно визначає повну кількість незалежних контекстів прикладних процесів у системі із загальною пам'яттю, що виконуються паралельно, які операційна система змушена враховувати. Я говорю «змушена», тому що вона не може керувати порядком виконання двох процесів, що знаходяться на різних логічних процесорах. Це відноситься до гіперпотоків: хоча вони і працюють «послідовно» на одному ядрі, конкретний порядок диктується апаратурою і недоступний для спостереження або управління програмами.

Найчастіше операційна система ховає від кінцевих додатків особливості фізичної топології системи, де вона запущена. Наприклад, три наступні топології: (2, 1, 1), (1, 2, 1) та (1, 1, 2) - ОС представлятиме у вигляді двох логічних процесорів, хоча перша з них має два процесори, друга - два ядра, а третя - лише два потоки.



Windows Task Manager показує 8 логічних процесорів; але скільки це в процесорах, ядрах та гіперпотоках?


Linux top показує 4 логічні процесори.

Це досить зручно для творців прикладних додатків - їм не доводиться мати справу часто несуттєвими для них особливостями апаратури.

Програмне визначення топології

Звичайно, абстрагування топології в однину логічних процесорів у ряді випадків створює достатньо підстав для плутанини та непорозумінь (у гарячих Інтернет-спорах). Обчислювальні програми, які бажають вичавити з заліза максимум продуктивності, вимагають детального контролю над тим, де будуть розміщені їх потоки: ближче один до одного на сусідніх гіперпотоках або навпаки, подалі на різних процесорах. Швидкість комунікацій між логічними процесорами у складі одного ядра чи процесора значно вища, ніж швидкість передачі між процесорами. Можливість неоднорідності в організації оперативної пам'ятітакож ускладнює картину.

Інформація про топологію системи в цілому, а також положення кожного логічного процесора в ІА-32 доступна за допомогою інструкції CPUID. З появи перших багатопроцесорних систем схема ідентифікації логічних процесорів кілька разів розширювалася. На даний момент її частини містяться у аркушах 1, 4 та 11 CPUID. Який із аркушів слід дивитися, можна визначити з наступної блок-схеми, взятої зі статті:


Я не буду тут стомлювати всіма подробицями окремих частин цього алгоритму. Якщо виникне цікавість, то цьому можна присвятити таку частину цієї статті. Відішлю цікавого читача до , в якій це питання розбирається максимально докладно. Тут я спочатку коротко опишу, що таке APIC і як він пов'язаний із топологією. Потім розглянемо роботу з листом 0xB (одинадцять у десятковому численні), який зараз є останнім словом в «апікобудуванні».

APIC ID
Local APIC (advanced programmable interrupt controller) - це пристрій (що нині входить до складу процесора), який відповідає за роботу з перериваннями, що приходять до конкретного логічного процесора. Свій власний APIC має кожен логічний процесор. І кожен із них у системі повинен мати унікальне значення APIC ID. Це число використовується контролерами переривань для адресації при доставці повідомлень, а рештою (наприклад, операційною системою) - для ідентифікації логічних процесорів. Специфікація на цей контролер переривань еволюціонувала, пройшовши від мікросхеми Intel 8259 PIC через Dual PIC, APIC та xAPIC до x2APIC.

На даний момент ширина числа, що зберігається в APIC ID, досягла повних 32 біт, хоча в минулому воно було обмежено 16, а ще раніше – лише 8 бітами. Нині залишки старих днів розкидані по всьому CPUID, проте в CPUID.0xB.EDX повертаються всі 32 біти APIC ID. На кожному логічному процесорі, незалежно виконує інструкцію CPUID, буде повертатися своє значення.

З'ясування родинних зв'язків
Значення APIC ID саме собою нічого не говорить про топологію. Щоб дізнатися, які два логічні процесори знаходяться всередині одного фізичного (тобто є «братами» гіпертредами), які два - всередині одного процесора, а які виявилися зовсім у різних процесорах, треба порівняти їх значення APIC ID. Залежно від ступеня кревності деякі їх біти збігатимуться. Ця інформація міститься в підлистях CPUID.0xB, які кодуються за допомогою операнда в ECX. Кожен з них описує положення бітового поля одного з рівнів топології в EAX (точніше, число біт, які потрібно зрушити в APIC ID вправо, щоб усунути нижні рівні топології), а також тип цього рівня - гіперпотік, ядро ​​або процесор - в ECX.


У логічних процесорів, що знаходяться всередині одного ядра, збігатимуться всі біти APIC ID, крім тих, що належать полю SMT. Для логічних процесорів, що у одному процесорі, - все біти, крім полів Core і SMT. Оскільки кількість підлистів у CPUID.0xB може зростати, дана схема дозволить підтримати опис топологій і з більшим числом рівнів, якщо в майбутньому виникне потреба. Більше того, можна буде запровадити проміжні рівні між існуючими.

Важливе наслідок організації цієї схеми у тому, що у наборі всіх APIC ID всіх логічних процесорів системи може бути «дірки», тобто. вони не йдуть послідовно. Наприклад, у багатоядерному процесорі з вимкненим HT всі APIC ID можуть виявитися парними, тому що молодший біт, який відповідає за кодування номера гіперпотоку, буде завжди нульовим.

Зазначу, що CPUID.0xB - не єдине джерело інформації про логічні процесори, доступне операційній системі. Список всіх процесорів, доступний їй, разом із значеннями APIC ID, кодується в таблиці MADT ACPI .

Операційні системи та топологія

Операційні системинадають інформацію про топологію логічних процесорів додатків за допомогою своїх власних інтерфейсів.

У Linux інформація про топологію міститься в псевдофайлі /proc/cpuinfo, а також виведенні команди dmidecode. У прикладі нижче я фільтрую вміст cpuinfo на деякій чотириядерній системі без HT, залишаючи тільки записи, що стосуються топології:

Прихований текст

[email protected]:~$ cat /proc/cpuinfo |grep "processor\|physical\ id\|siblings\|core\|cores\|apicid" processor: 0 physical id: 0 siblings: 4 core id: 0 cpu cores: 2 apicid: 0 initial apicid: 0 processor: 1 physical id: 0 siblings: 4 core id: 0 cpu cores: 2 apicid: 1 initial apicid: 1 processor: 2 physical id: 0 siblings: 4 core id: 1 cpu cores: 2 2 initial apicid: 2 processor: 3 physical id: 0 siblings: 4 core id: 1 cpu cores: 2 apicid: 3 initial apicid: 3

У FreeBSD топологія повідомляється через механізм sysctl у змінній kern.sched.topology_spec у вигляді XML:

Прихований текст

[email protected]:~$ sysctl kern.sched.topology_spec kern.sched.topology_spec: 0, 1, 2, 3, 4, 5, 6, 7 0, 1, 2, 3, 4, 5, 6, 7 0, 1 THREAD groupSMT group 2, 3 THREAD groupSMT group 4, 5 THREAD groupSMT group 6, 7 THREAD groupSMT group

У MS Windows 8 інформацію про топології можна побачити у диспетчері завдань Task Manager.

Складання