Linux і симетрична багатопроцесорна система (вихідні коди) - програмні продукти

М. Тім Джонс, інженер-консультант, Emulex

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

Перш ніж обговорювати застосування багатопроцесорної обробки в Linux, давайте поглянемо на її історію.

Історія багатопроцесорної обробки

Класифікація багатопроцесорних архітектур Флінна.

Один потік команд, один потік даних (SISD - Single Instruction, Single Data) - типова однопроцесорна архітектура. Многопроцессорная архітектура Багато потоків команд, багато потоків даних (MIMD - Multiple Instruction, Multiple Data) містить окремі процесори, які оперують незалежними даними (паралелізм управління). Нарешті, Один потік команд, багато потоків даних (SIMD - Single Instruction, Multiple Data) має ряд процесорів, що оперують різнотипними даними (паралелізм даних).

Многопроцессорная обробка зародилася в середині 1950-х в ряді компаній, деякі з яких ви знаєте, а деякі, можливо, вже забули (IBM, Digital Equipment Corporation, Control Data Corporation). На початку 1960-х Burroughs Corporation представила симетричний мультипроцессор типу MIMD з чотирма CPU, що має до шістнадцяти модулів пам'яті, з'єднаних координатним соединителем (перша архітектура SMP). Широко відомий і вдалий CDC 6600 був представлений в 1964 і забезпечував CPU десятьма подпроцессорамі (периферійними процесорами). В кінці 1960-х Honeywell випустив іншу симетричну мультипроцесорну систему з восьми CPU Multics.

У той час як багатопроцесорні системи розвивалися, технології також йшли вперед, зменшуючи розміри процесорів і збільшуючи їх здатності працювати на значно більшій тактовій частоті. У 1980-х такі компанії, як Cray Research, представили багатопроцесорні системи та UNIX®-подібні операційні системи, які могли їх використовувати (CX-OS).

В кінці 1980-х з популярністю однопроцесорних персональних комп'ютерів, таких як IBM PC, спостерігався занепад в багатопроцесорних системах. Але зараз, через двадцять років, многопроцессорная обробка повернулася до тих же самим персональних комп'ютерів у вигляді симетричною багатопроцесорної обробки.

Джин Амдаль (Gene Amdahl), комп'ютерний архітектор і співробітник IBM, розробляв в IBM комп'ютерні архітектури, створив однойменну фірму, Amdahl Corporation та ін. Але популярність йому приніс його закон, в якому розраховується максимально можливе поліпшення системи при поліпшенні її частини. Закон використовується, головним чином, для обчислення максимального теоретичного поліпшення роботи системи при використанні декількох процесорів (дивись Малюнок 1).

Малюнок 1. Закон Амдаля для розпаралелювання процесів

Використовуючи рівняння, показане на рисунку 1, ви можете вирахувати максимальне поліпшення продуктивності системи, що використовує N процесорів і фактор F. який показує, яка частина системи не може бути распараллелена (частина системи, яка є послідовною за своєю природою). Результат наведено на рисунку 2.

Малюнок 2. Закон Амдаля для системи, що має до десяти CPU

Верхня лінія на рисунку 2 показує число процесорів. В ідеалі це те, що ви хотіли б побачити після додавання додаткових процесорів для вирішення завдання. На жаль, через те що не всі в задачі може бути распараллеліть і є непродуктивні витрати в управлінні процесорами, прискорення виявляється трохи менше. Внизу (лілова лінія) - випадок завдання, яка на 90% послідовна. Кращому нагоди на цьому графіку відповідає коричнева лінія, яка зображує завдання, яка на 10% послідовна і, відповідно, на 90% - параллелізуема. Навіть в цьому випадку десять процесорів працюють зовсім не набагато краще, ніж п'ять.

Многопроцессорная обробка і ПК

Архітектура SMP - одна з тих, де два або більше ідентичних процесорів з'єднані один з одним за допомогою розділяється пам'яті. У всіх них однаковий доступ до пам'яті, що (однаковий час очікування доступу до простору пам'яті). Протилежністю їй є архітектура неоднорідного доступу до пам'яті (NUMA - Non-Uniform Memory Access). Наприклад, у кожного процесора є своя власна пам'ять і доступ до пам'яті, що з різним часом очікування.

Слабосвязанних многопроцессорная обробка

Ранні SMP системи Linux були слабо зв'язаної багатопроцесорними системами, тобто побудованими з декількох окремих систем, пов'язаних високошвидкісним з'єднанням (таким як 10G Ethernet, Fibre Channel або Infiniband). Інша назва такого типу архітектури - кластер (дивіться Малюнок 3), для якого популярним рішенням залишається проект Linux Beowulf. Кластери Linux Beowulf можуть бути побудовані з доступного обладнання і звичайного підключення до мережі, такого як Ethernet.

Малюнок 3. слабо зв'язаної многопроцессорная архітектура

Побудова систем зі слабо зв'язаної многопроцессорной архітектурою просто (спасибі проектам на кшталт Beowulf), але має свої обмеження. Створення великої многопроцессорной мережі може зажадати значних потужностей і місця. Більш серйозна перешкода - матеріал каналу зв'язку. Навіть з високошвидкісною мережею, такий як 10G Ethernet, є межа масштабованості системи.

Сільносвязанная многопроцессорная обробка

Сільносвязанная многопроцессорная обробка відноситься до обробки на рівні кристала (CMP - chip-level multiprocessing). Уявіть слабо зв'язаної архітектуру, зменшену до рівня кристала. Це і є ідея Сільносвязанная багатопроцесорної обробки (також званої багатоядерним обчисленням). На одній інтегральної мікросхемі кілька кристалів, спільна пам'ять і з'єднання утворюють добре інтегроване ядро ​​для багатопроцесорної обробки (дивіться Малюнок 4).

Асиметрична многопроцессорная обробка (ASMP --Asymmetric multiprocessing), дев'ять CPU

Для того щоб використовувати SMP з Linux на сумісному з SMP обладнанні, необхідно правильно налаштувати ядро. Опція CONFIG_SMP повинна бути включена під час налаштування ядра, щоб ядро ​​знало про SMP. Якщо таке ядро ​​буде працювати на многопроцессорном хості, ви зможете визначити кількість процесорів і їх тип за допомогою файлової системи proc.

Спочатку ви отримуєте число процесорів з файлу cpuinfo в / proc, використовуючи grep. Як видно з лістингу 1, ви використовуєте опцію - лічильник (-c) рядків, що починаються зі слова processor. Наведено також вміст файлу cpuinfo. Як приклад взята материнська плата Xeon на двох кристалах.

Лістинг 1. Використання файлової системи proc для отримання інформації про CPU

Коли тільки з'явився Linux 2.0, підтримка SMP складалася з основної системи блокування, яка впорядковувала доступ в системі. Пізніше невеликий прогрес в підтримці SMP був, але тільки з ядром 2.6 нарешті проявилася вся сила SMP.

Ядро 2.6 представило новий 0 (1) планувальник, який включав кращу підтримку для систем SMP. Ключовий була можливість балансувати навантаження на всі доступні CPU, у міру сил уникаючи перемикання процесів між процесорами для більш ефективного використання кеша. Що стосується продуктивності кеша, згадайте з рисунка 4, що коли завдання взаємодіє з одним CPU, переміщення її на інший вимагає залучення кеша. Це збільшує час очікування доступу до пам'яті завдання, поки її дані знаходяться в кеші нового CPU.

SMP в ядрі
Щоб зрозуміти, як SMP инициализируется для заданої архітектури, подивіться файли smp.c або smpboot.c всередині ядра. / Linux / arch // Kernel / (для більшості архітектур і платформ).

Ядро 2.6 зберігає пару runqueue для кожного процесора (минулий і активний runqueue). Кожен runqueue підтримує 140 пріоритетів, з яких 100 використовується для задач в реальному часі, а решта 40 для користувача завдань. Завданням даються відрізки часу для виконання, а коли вони використовують свій час, вони переміщаються з активного runqueue в минулий. Таким чином здійснюється рівноправний доступ до CPU для всіх завдань (блокування тільки окремих CPU).

З чергою завдань на кожному CPU робота може бути збалансована, даючи зважену навантаження всіх CPU в системі. Кожні 200 мілісекунд планувальник виконує балансування завантаження, щоб перерозподілити завдання і зберегти баланс в комплексі процесорів.

Потоки робочих просторів: розвиваючи силу SMP

У ядрі Linux була проведена велика робота для розвитку SMP, але операційної системи, самої по собі, недостатньо. Згадайте, що сила SMP полягає в TLP. Окремі монолітні (одно-потокові) програми не можуть використовувати SMP, але SMP може використовуватися в програмах, які складаються з багатьох потоків, які можуть бути розподілені між ядрами. Поки один потік чекає виконання операції I / O, інший може робити корисну роботу. Таким чином, потоки працюють, перекриваючи час очікування один одного.

Потоки стандарту Portable Operating System Interface (POSIX) (інтерфейс яку переносять операційної системи) є прекрасним способом побудувати потокові додатки, які можуть використовувати SMP. Потоки стандарту POSIX забезпечують механізм роботи з потоками, а також загальну пам'ять. Коли програма активізується, створюється деяка кількість потоків, кожен з яких підтримує свій власний стек (локальні змінні і стан), але розділяє простір даних батька. Всі створені потоки поділяють цей же самий простір даних, але саме тут криється проблема.

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

Лістинг 2. Використання pthread_mutex_lock і unlock для створення критичних секцій


Якщо кілька потоків намагаються заблокувати семафор після початкового виклику нагорі, вони блокуються, і їх запити ставляться в чергу, поки не виконається виклик pthread_mutex_unlock.

Захист змінної ядра для SMP

Коли кілька ядер в процесорі працює паралельно для ядра ОС, бажано уникати спільного використання даних, які специфічні для даного ядра процесора. З цієї причини ядро ​​2.6 представило концепцію змінних для кожного ядра, які пов'язані з окремими CPU. Це дозволяє оголошувати змінні для CPU, які найбільш часто використовуються саме цим CPU, що мінімізує вимоги блокувань і покращує виконання.

Визначення змінних окремого ядра проводиться за допомогою макросу DEFINE_PER_CPU. якому ви передаєте тип і ім'я змінної. Оскільки макрос надходить як l-value, тут же ви можете форматувати її. У наступному прикладі (з ./arch/i386/kernel/smpboot.c) визначається змінна, що представляє стан для кожного CPU в системі.


Макрос створює масив змінних, одну на кожен екземпляр CPU. Для отримання змінної окремого CPU використовується макрос per_cpu разом з функцією smp_processor_id. повертає поточний ідентифікатор CPU, для якого в даний момент виконується програма.


Ядро надає інші функції для блокування кожного CPU і динамічного виділення змінних. Ці функції можна знайти в ./include/linux/percpu.h.

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

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

Схожі статті