Linux і симетрична багатопроцесорна система (исходники), Різне, Програмування, статті

Швидкодія системи 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. Закон Амдаля для розпаралелювання процесів

В CMP кілька CPU пов’язані загальною шиною з пам’яттю (кеш другого рівня). Кожен процесор також має свою власну швидкодіючу пам’ять (кеш першого рівня). Сільносвязанная природа CMP дозволяє дуже короткі фізичні відстані між процесорами і пам’яттю і, внаслідок цього, мінімальний час очікування доступу до пам’яті і більш високу продуктивність. Такий тип архітектури добре працює в багатопоточних програмах, де потоки можуть бути розподілені між процесорами і виконуватися паралельно. Це називається паралелізм на рівні потоків (TPL – thread-level parallelism).


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


Таблиця 1. Вибірка пристроїв CMP






































Виробник Пристрій Опис
IBM POWER4 SMP, два CPU
IBM POWER5 SMP, два CPU, чотири паралельні потоки
AMD AMD X2 SMP, два CPU
Intel® Xeon SMP, два або чотири CPU
Intel Core2 Duo SMP, два CPU
ARM MPCore SMP, до чотирьох CPUs
IBM Xenon SMP, три Power PC CPU
IBM Cell Processor Асиметрична багатопроцесорна обробка (ASMP – Asymmetric multiprocessing), дев’ять CPU

Конфігурація ядра


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


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


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





mtj@camus:~$ grep -c ^processor /proc/cpuinfo
8
mtj@camus:~$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 15
model : 6
model name : Intel(R) Xeon(TM) CPU 3.73GHz
stepping : 4
cpu MHz : 3724.219
cache size : 2048 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 2
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 6
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr
pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm
pbe nx lm pni monitor ds_cpl est cid xtpr
bogomips : 7389.18

processor : 7
vendor_id : GenuineIntel
cpu family : 15
model : 6
model name : Intel(R) Xeon(TM) CPU 3.73GHz
stepping : 4
cpu MHz : 3724.219
cache size : 2048 KB
physical id : 1
siblings : 4
core id : 3
cpu cores : 2
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 6
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr
pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm
pbe nx lm pni monitor ds_cpl est cid xtpr
bogomips : 7438.33
mtj@camus:~$

SMP і ядро ​​Linux


Коли тільки з’явився 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_t crit_section_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_lock( &crit_section_mutex );
/ * Усередині критичної секції. Доступ до пам’яті тут безпечний * Для пам’яті, захищеної crit_section_mutex.
*/
pthread_mutex_unlock( &crit_section_mutex );

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


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


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


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






/* State of each CPU. */
DEFINE_PER_CPU(int, cpu_state) = { 0 };

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






per_cpu( cpu_state, smp_processor_id() ) = CPU_ONLINE;

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


Висновок


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


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

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*