Методи збільшення обчислювальної продуктивності

Дякую вам за підтримку!

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

Перше поділ відноситься до числа процесорів: якісні методи передбачають прискорення роботи ЦП при незмінному його / їх кількості, кількісні - нарощування числа ЦП з метою скласти їх зусилля. Багатопроцесорні архітектури застосовуються, коли інші способи вже впроваджені і більш не ефективні, і при належному вмінні інженерів і програмістів дають відмінний результат (якщо, звичайно, завдання добре распараллеливается) - сукупна продуктивність системи зростає майже лінійно числу процесорів завдяки ретельно злагодженій синхронізації взаємодій обчислювальних вузлів. В останніх випусках рейтингу найшвидших суперкомп'ютерів планети Top500 майже всі машини використовують кластерну архітектуру, засновану на концепції масового паралелізму (MPP, massively parallel processing). У цих обчислювальних монстрів, які займають цілі зали, одночасно працюють десятки, а скоро, можливо, і сотні тисяч процесорів.

Методи збільшення обчислювальної продуктивності

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

Збільшення частоти досяжно двома способами. Фізично: зменшуючи проектні норми, тобто мінімальні розміри провідників і транзисторів на чіпі - за рахунок цього останні працюють швидше і споживають менше енергії (це головна причина, чому свого часу світ відмовився від ТТЛ і ЕСЛ-сімейств логіки на користь КМОП - у тих при зменшенні розмірів таких масштабних привілеїв НЕ було). І архітектурно: збільшуючи частотний стелю поділом процесора на окремі стадії, тобто організацією обчислювального конвеєра. А якщо він вже є - збільшенням числа цих стадій.

Методи збільшення обчислювальної продуктивності

Розглянемо для прикладу заводик, який випускає якусь деталь. Поки на ньому 1 верстат, що обробляє заготовку за 6 хвилин. Продуктивність - 10 деталей / год. Однак процес можна розділити на 3 окремих слабо пов'язаних етапу, які можна виконувати одночасно над трьома деталями - кожна на своїй стадії. Ставимо три верстата замість одного: перший над кожною деталлю працює 1 хвилину, другий 3 і третій 2. Загальна продуктивність конвеєра обмежується найповільнішої його частиною - другим верстатом. І хоча інші часто простоюють, наш заводик випускає вже 20 деталей / год. Щоб оптимізувати конвеєр, слід зробити роботу його стадій максимально рівномірної - передати частину роботи з другого верстата на перший так, щоб обидва працювали за 2 хвилини. Однак це не завжди виходить, зате виявляється, що ми можемо найповільнішу частина системи ( «пляшкове горлечко») розділити на 2 етапи - нехай по 1 і 2 хвилини кожен. Тепер у нас 4 верстати з темпом роботи 1, 1, 2 і 2 хв. відповідно. Все б добре, але кількість заліза збільшилася вчетверо, а ось швидкість роботи - всього втричі. А чи не нарізати нам конвеєр ще дрібніші - поставимо 6 верстатів, що працюють по одній хвилині. Тепер ми витратили 6-кратну кількість засобів виробництва і отримали 6-кратний вихід продукту.

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

Продуктивність за такт характеризується двома взаємно зворотними величинами - середнє число тактів для виконання однієї команди (clocks per instruction, CPI) і середнє число виконаних за такт команд (instructions per clock, IPC). До появи суперскалярні ЦП головним способом прискорення крім частотної гонки було зменшення CPI (або збільшення IPC, хоча такий термін ще не застосовувався через непотрібність). Це можна відвести до якісного поліпшення, тому що головний спосіб один - замість розмноження або розгону наявних структур додаються нові, апаратно (тобто швидше) обчислюють те, що раніше неспішно робилося в блоках загального призначення.

У 386-го процесора подвоїли чергу предзагрузкі команд (prefetch queue) до 12 байт, розширили до 3 байт розрядність декодера, додали після нього буфер мікрокоманд (тепер це ЦП з 3-стадійним конвеєром), і замінили послідовний регістр зсуву паралельним (barrel shifter, виробляє будь-який вид зсуву на будь-яке число біт за фіксований час). 486-й наділений конвеєрним виконанням, вбудованим речовим блоком, буфером запису і внутрішнім кешем L1 (той, що на платі, тепер L2). 486DX2 отримав можливість кешувати в L1 запис (write-back, не у всіх моделях), а 486DX4 - подвоєний кеш і матричний помножувач (правда, поки тільки цілочисельний і половинної розрядності - 16 · 16). Всі подібні поліпшення тривають досі - наприклад, до появи архітектур AMD К10 і Intel Core 2 процесори виконували арифметичні команди над векторними речовими даними з темпом 2 такту - векторні АЛУ і умножители там половинної, 64-бітної ширини, а у К10 і Core 2 вони стали полноразряднимі.

Головний такий милицю - позачергове виконання (Out-of-order execution, OoOE або OOO): мопи накопичуються в спеціальному перетасовочном буфері (reorder buffer, ROB) і зчитуються звідти вже не в зазначеному програмою порядку, а в довільному при появі можливості одночасного виконання. Оскільки буфер вміщує десятки мопов, цього вистачить на 3-4 запускаються за такт команди, навіть далеко стоять один від одного (якщо вони вже лічені і декодовані). Особливо добре OOO працює з ще одним механізмом поліпшення - перейменування регістрів видаляє помилкові взаємозалежності по операндам наступних команд від попередніх. Однак і це поки не дозволяє підняти IPC понад 4-х. Частково тому, що мопов більше, ніж команд, так що зчитуючи 4 команди, ми отримуємо 5-10 мопов, для зберігання і виконання яких буде потрібно таку ж кількість вільних ресурсів кожен такт. Тому придумана схема злиття (fusion), що дозволяє об'єднувати на час попередньої підготовки пару команд (поки пару, але цілком можливо, що більше ні в кого не вийде). Для мопов це мікросліяніе: декодер генерує злиті мопи, які при розподілі запускаються в пару різних ФУ, виконуючи там різні операції, що економить число зайнятих мопами конвеєрних шин і осередків буферів. Для зовнішніх команд це макросліяніе: декодер трактує деякі пари команд як одну, генеруючи для неї 1 моп (можливо, теж злитий), що в окремих випадках також піднімає IPC.

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

Методи збільшення обчислювальної продуктивності

За кількістю пунктів вище видно, що додавання додаткових наборів команд - один з основних методів збільшення швидкості ЦП. Вже зараз загальна кількість команд в архітектурі x86 перевалило за 1000, що призвело до виключного ускладнення декодерів і ФУ, а також до сильного утруднення програмування і оптимізації на асемблері. Проте, Intel (а саме вона ввела переважна більшість таких наборів) продовжує постачати нові процесори черговими видами інструкцій, змушуючи те ж саме робити і конкурента.

Методи збільшення обчислювальної продуктивності

Передбачити розгалуження технічної думки інженерів, архітекторів і мікроелектронників, які намагаються знайти черговий спосіб прискорити процесор - завдання не простіше, ніж самому ЦП передбачити розгалуження в виконуваній програмі з 99% -вою точністю. Проте, якщо подивитися з висоти на історію методів прискорення обчислень, помічається цікава закономірність: спочатку якийсь спосіб з'являється у великих машинах - мейнфреймах і суперкомп'ютерах, де він перевіряється і відточується. Потім, завдяки прогресу в мікроелектроніці, то, що раніше займало шафи і зали, стало можливим умістити на одну плату, потім в корпус процесора, а потім і на його чип. Конвеєри, кеші, суперскалярність, ОOО, SIMD і інше - все це родом з 60-80-х. Треба думати, що подібне буде відбуватися і далі - просто подивимося на сьогоднішні суперкомп'ютери і постараємося через 10-20 років зробити те ж саме в одній мікросхемі. Однак тут чекає несподівана розв'язка - більшість найпотужніших комп'ютерів планети сьогодні самі засновані на архітектурі x86. Просто вона виявилася настільки успішною і універсальної, так швидко увібрала в себе все краще від конкурентів, що, навпаки, це суперкомп'ютери тепер робляться на архітектурі, спочатку створеної для персоналок. Фактично, обчислювальна техніка, зробивши повне коло, вперлася сама в себе.

Можливо, порятунком буде нова, некремніевая мікроелектроніка (взагалі-то, вона вже давно «нано-») - або вуглецева на графені і нанотрубках, або квантова на спінтронних транзисторах або «заплутаних» частинках. А може, і без електрики взагалі - фотоніка активно вивчається тієї ж Intel, яка вже домоглася створення інтегральних волноводов і досліджує методи створення фотонного транзистора. Все це здатне підняти частотний стелю (адже відмовлятися від ідеї синхронних обчислювачів не збираються, хоча, наприклад, людський мозок є «нетактіруемой обчислювальною машиною»), а ось які будуть якісні ідеї (крім чергового SSE8) - точно ніхто не знає. Тому горезвісний закон Мура (який ніякий не закон, а емпіричне правило, не надто чітко, але все ж дотримуватися протягом десятиліть) останнім часом постійно ставиться під сумнів - протягнемо ще рочків п'ять, або настане-таки кінець експоненціального зростання?

Втім, зростання може і не знадобитися. Як сказав в 90-х один користувач, що мав відношення до ВПК, «мого комп'ютера з 486-м процесором з головою вистачило б для управління всією угрупованням радянських військових супутників, але його не вистачає на одночасний набір і роздрук тексту в Word'е». Десятки гігафлоп і доступність програмування на мовах високого рівня, що приховують складність апаратних тонкощів, настільки розбестили багатьох програмістів, що вони і думати перестали про якусь там економії та оптимізації - навіщо, якщо користувач просто почекає півроку і проапгрейдить, а за цей час краще не оптимізувати поточну версію програми, а зробити нову і продати її дорожче. Коли програмування з творчості перетворилося в потокове ремесло (масовий ПК передбачає масове ПО і масового програміста), головними стали не якість, швидкість і зручність, а способи швидше заробити гроші. Виходить, що після впровадження всіх відносно простих і недорогих прискорювачів продуктивності головним способом зробити комп'ютер ще швидше може виявитися оптимізація програм і економія вже наявних ресурсів. Але це вже тема іншої статті.

Схожі статті