Багатоядерні процесори і проблеми паралельної обробки

  1. Модель програмування на основі потоків
  2. Глибина стека викликів
  3. Малюнок 1. Внутрішня структура та зростання стека викликів
  4. досяжність об'єктів
  5. загальні об'єкти
  6. Малюнок 2. Спільна пам'ять
  7. послідовне програмування
  8. Малюнок 3. Один потік
  9. висновок
  10. Відмова від відповідальності
  11. Ресурси для скачування

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

Закон Мура - зроблене в 1965 році Гордоном Муром пророкування, що число компонентів інтегральних схем буде подвоюватися кожні 18-24 місяці - виявився вірним, і очікується, що він буде дотримуватися до 2015-2020 року (див. Розділ ресурси ). До 2005 року тактова частота процесорів теж постійно підвищувалася, і цього було досить для підвищення продуктивності всіх додатків, що виконуються цими процесорами. Спільнота розробників додатків отримувало дотацію на підвищення продуктивності, мало або взагалі нічого не вкладаючи в поліпшення алгоритмів.

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

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

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

Модель програмування на основі потоків

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

Паралелізм на основі потоків має наступні переваги:

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

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

Глибина стека викликів

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

Внутрішні деталі процесу виклику методу показані на малюнку 1.

Малюнок 1. Внутрішня структура та зростання стека викликів
Чому паралельна обробка додатків на основі потоків неадекватна епосі багатоядерних процесорів   Закон Мура - зроблене в 1965 році Гордоном Муром пророкування, що число компонентів інтегральних схем буде подвоюватися кожні 18-24 місяці - виявився вірним, і очікується, що він буде дотримуватися до 2015-2020 року (див

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

досяжність об'єктів

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

Реалізація стека викликів Java ™ розрахована на автоматичне виключення всіх своїх посилань при поверненні виклику методу. Це прийнятно, коли JVM працює без високого навантаження. Але може стати проблемою, коли JVM має справу з великим числом активних потоків. Наприклад, якщо кожен потік займає до 5 MB невикористовуваних дійсних посилань в стеці викликів, і працює 100 потоків, то JVM не зможе зібрати 500 МБ сміття простору купи, бо на них посилаються змінні і параметри стека викликів. На 32-розрядної машині це може скласти 25% всієї пам'яті, доступної для JVM.

загальні об'єкти

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

Малюнок 2. Спільна пам'ять

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

послідовне програмування

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

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

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

Тепер подумаємо про те, як сучасний сервер додатків JEE виконує запит користувача. На один запит користувача він виділяє один потік. Як показано на малюнку 3, в цьому потоці виконуються всі інструкції, від входу до взаємодії з базою даних, виклику Web-сервісів, передачі по мережі, логіки обчислень і т.п.

Малюнок 3. Один потік

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

висновок

Нить - відмінний спосіб ефективного використання ресурсів центрального процесора. Але в міру розвитку системи спільноти розробників додатків і ОС поширюють многопоточность на паралелізм рівня додатки. Розробники додатків почали використовувати програмування на основі потоків для послідовного виконання всієї логіки додатка. Тим часом тенденція в напрямку багатоядерних процесорів набирає силу, число ядер неухильно зростає, і послідовне програмування на основі потоків стає все менш ефективним.

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

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

Відмова від відповідальності

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

Ресурси для скачування

Схожі теми

  • Оригінал статті: Multicore CPUs and the concurrency changes they bring .
  • New life for Moore's Law (Michael Kanellos, CNET, квітень 2005 року): прогнози галузевих експертів щодо розвитку технології мікропроцесорів на найближче і віддалене майбутнє.
  • Multicore Processors - A Necessity (Bryan Schauer, 2008 року): огляд технології багатоядерних процесорів і завдань, які вони ставлять перед програмістами.
  • Is Parallel Programming Hard, And, If So, What Can You Do About It? (Paul E. McKenney, ed., 2011 р): ця книга допомагає розробникам зрозуміти, як програмувати паралельні машини із загальною пам'яттю.
  • Java, Python, Ruby, Linux, Windows are all Doomed (Russel Winder, 2010 р): в цій доповіді досліджуються деякі питання, пов'язані з операційними системами, прикладним ПО, програмуванням і мовами програмування, які ставить перед розробниками наступний етап многоядерной революції.
  • Concurrent Programming for Scalable Web Architectures (Benjamin Erb, квітень 2010 р): дисертація, яка містить огляд конкуруючих підходів до реалізації паралелізму і їх використання.
  • Software Pipelines and SOA: Releasing the Power of Multi-Core Processing (Cory Isaacson, Addison-Wesley, 2009 г.): книга, що знайомить читача з підходом до реалізації паралельної обробки, званим "каналами програмного забезпечення" (Software Pipelines).
  • The Future of Computing Performance: Game Over or Next Level? (Samuel H. Fuller and Lynette I. Millett, eds., The National Academies Press, 2011 р): книга про фактори, які призвели до обмежень розвитку окремих мікропроцесорів, проблеми паралельних обчислень і архітектури, а також про необхідність досліджень, практичної роботи і навчання для подолання цих труднощів.
  • Software and the Concurrency Revolution (Herb Sutter and James Larus, AMC Queue, вересень 2005 року): автори статті доводять, що для використання всієї потужності багатоядерних процесорів від індустрії програмного забезпечення потрібні нові інструменти і нове мислення. (Повний текст надається тільки передплатникам).
  • Java concurrency (DeveloperWorks, серпень 2011 року): про багатопотоковому програмуванні на мові Java і про альтернативні підходи до платформи Java, націлених на використання обладнання сучасних багатоядерних процесорів.

Підпишіть мене на повідомлення до коментарів

Is Parallel Programming Hard, And, If So, What Can You Do About It?
The Future of Computing Performance: Game Over or Next Level?