Паралельноє програмирование

ЗМІСТ

	ВСТУП	2

		1	БАГАТОЯДЕРНІ АМД ПРОЦЕСОРИ	5

	1.1 АМД ПРОЦЕСОРИ	5

	1.2 AMD Opteron/Athlon64	7

	1.3 AMD Phenom	8

	1.4 AMD Turion	13

		2	ЗАСОБИ МОВ С#, ADA ДЛЯ ПРОГРАМУВАННЯ ПОТОКІВ	16

	2.1 Вирішення завдання   синхронізації в мові С#	16

	2.2  Засоби синхронізації в мові С#	20

	2.3 ВИРІШЕННЯ ЗАВДАННЯ  СИНХРОНІЗАЦІЇ В МОВІ АДА	29

		3	АПАРАТНИЙ КОМПЛЕКС	34

	3.1 Компютерна система	34

	3.2 Процесор	34

	3.4 Оперативна память	36

	3.4 Жорсткий диск	36

	3.5 Корпус	37

	4    РОЗРОБКА ПРОГРАМ	38

	4.1 Задача 	38

	4.2 Задача 	41

	4.2 Задача 	44C:\www\doc2html\work\bestreferat-232132-13965101163743\input\Бакалаврська Вайнагій Олександр.docx - _Toc263737444

	4.4 Тестування програм	47

	ВИСНОВКИ	51

	СПИСОК ВИКОРИСТАНОЇ ЛІТЕРАТУРИ	52

		













ВСТУП



	Сьогодні все більше комп'ютерів оснащується багатоядерними процесорами. Такі чіпи – наприклад Core| Duo| корпорації Intel| або Athlon| 64 X2| від AMD| – містять|утримують| два (Dual| Core|) або навіть чотири (Quad| Core|) процесори. 

Довгий час виробники процесорів – для підвищення продуктивності процесорів підвищували їх тактову частоту. Проте|однак| при тактовій частоті більше 3,8 ГГц чіпи просто перегріваються, відповідно, про вигоду можна забути.

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

Та все ж управління паралельними завданнями|задачами| теж|також| вимагає часу і задіює ресурси ПК, крім того, часом для вирішення однієї з них доводиться чекати результату виконання інший. Тому на практиці двоядерні процесори не виробляють|справляють| обчислення|підрахунку| в два рази швидше одноядерних: хоча приріст швидкодії і виявляється|опиняється| значним, але|та| при цьому він залежить від типа|типу| додатка|застосування|. В|у| ігор, які поки що зовсім не використовують нову технологію, швидкодію, на жаль, збільшується всього на 5% при однаковій тактовій частоті. А ось|от| оптимізовані під багатоядерні процесори програми для обробки музики і відео працюють швидше вже на 50%. 

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

Обробка відео: стискування|стиснення| і обробка відеофайлів відбуваються|походять| помітно швидше.	

Відтворення відео: якісне відтворення фільмів з|із| високим дозволом, наприклад з дисків Blu-ray| або HD-DVD| можливо лише з|із| багатоядерними процесорами. Адже при декомпресії такого відео, що містить|утримує| великі об'єми|обсяги| даних, процесор повинен виробляти|справляти| величезну кількість обчислень|підрахунків|;

ігри: перевага за швидкістю в|у| ігор поки|поки| невелика, вони дістали користь лише від великого розміру кеша процесора, встановленого|установленого| у вашому ПК. Пройде ще деякий час, поки|доки| з'являться|появлятимуться| ігри, які на багатоядерних процесорах працюватимуть помітно швидше;

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

Розробники корпорацій Intel| і AMD| постійно розробляють нові ідеї, як зробити процесори продуктивнішими і, як наслідок, більш конкурентоздатними|конкурентоспроможними|. Так, новітнє|найновіше| покоління багатоядерних процесорів, окрім іншого, використовує наступні|слідуючі| прийоми: 

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

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

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

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







































 БАГАТОЯДЕРНІ АМД ПРОЦЕСОРИ



1.1 АМД ПРОЦЕСОРИ



Перехід до багатоядерних процесорів стає основним напрямом|направленням| підвищення продуктивності. Такими є сучасні багатоядерні процесори |AMD.| Ці процесори по більшості показників продуктивності випереджають своїх х86-конкурентов| від Intel|, будучи лідерами цілочисельної продуктивності серед серверних процесорів, лише трохи поступаючись IBM| Power5| і Intel| Itanium| 2

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

Ще один підхід до вирішення даної проблеми був реалізований в VLIW/EPIC-архітектурі IA-64|, де частина|частка| проблем перекладена з апаратури на компілятор; проте|однак| сьогодні розробники визнають, що для високої продуктивності мікроархітектура важливіша.

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

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

Про випуск двоядерних процесорів з|із| архітектурою х86| в AMD| і Intel| оголосили майже одночасно.

AMD| пропонує 64-розрядні двоядерні процесори Opteron| для серверних систем і робочих станцій і 64-розрядні двоядерні Athlon64| — для настільних систем. Intel| використовує аналогічну 64-розрядну архітектуру EM64T| в своїх серверних процесорах Xeon| і «настільних» Pentium| 4.

Процесори Opteron| і до появи двоядерних версій випереджали своїх х86-конкурентов| від Intel| по продуктивності на більшості додатків|застосувань|. Opteron| взагалі є лідером серед всіх серверних процесорів по цілочисельній продуктивності, хоча на тестах SPECint2000| і поступається «настільному» Pentium| 4/3,8 ГГц. На тестах SPECfp2000| він поступається IBM| Power5| і Intel| Itanium| 2. Проте|однак| останні процесори досягають настільки|так| високих показників у тому числі і за рахунок дуже великої ємкості|місткості| кеша. Можна порівняти дані SPECfp2000| для Itanium| 2/1,4 ГГц з|із| 1,5-мегабайтним| кешем третього рівня (порівнянно з|із| 1 Мбайт в|у| Opteron|) і для Itanium| 2 з|із| тією ж частотою і кешем в 3 Мбайт. При такому збільшенні ємкості|місткості| кеша продуктивність Itanium| 2 зростає на 15% (дані для SGI| Altix| 350), а Opteron| відстає від Itanium| 2 з|із| кешем на 9 Мбайт всього на 30% (таблиця. 1). 

Таблиця 1. Продуктивність серверних процесорів на тестах SPECcpu2000| (пиковое/базовое значення) 





Рис1.1 Продуктивність серверних процесорів на тестах SPECcpu2000| (пікове/базове значення)









1.2 AMD Opteron/Athlon64

«Opteron»  (укр. Оптерон; кодова назва під час розробки Sledgehammer або K8) — перший мікропроцесор фірми AMD, заснований на 64-бітовій технології AMD64 (також званою x86-64). AMD створила цей процесор в основному для застосування на ринку серверів, тому існують варіанти Opteron для використання в системах з 1—16 процесорами.

Загальну|спільну| архітектуру серверів на базі Opteron| [1] в AMD| називають «архітектурою з|із| прямим з'єднанням|сполукою|», оскільки процесори «безпосередньо|напряму|» сполучені|з'єднані| з|із| оперативною пам'яттю за допомогою вбудованого контроллера пам'яті. В даний час|нині| Opteron| підтримує пам'ять DDR400|, що забезпечує пропускну спроможність 6,4 Гбайт/с на процесор. Із|із| зростанням|зростом| числа процесорів пропускна спроможність пам'яті зростає|росте| лінійно.

У двоядерному процесорі Athlon64| пропускна спроможність пам'яті з розрахунку на|розраховуючи на| ядро стає удвічі|вдвічі| менше|. У двоядерних Opteron| вона ділиться лише|тільки| між двома ядрами кожного процесора.

Крім того, Opteron і Athlon64 використовуть для підтримки когерентності кеша досконаліший|довершений| протокол MOESI|, що дає переваги в масштабуванні при роботі з|із| пам'яттю.  Пов'язаний з роботою протоколу MOESI| трафік в двоядерних процесорах Athlon64| не зачіпає комутатор, що не блокується, а використовує SRQ|, чергу системних запитів, що відповідає за управління ядрами і визначення їх пріоритету, і контроллер пам'яті. При цьому також зменшуються затримки, оскільки не додаються|добавляють| затримки на комутаторі.

Для багатопроцесорних серверів перевага|вищість| двоядерних процесорів Opteron| представляється важливішою|поважною|: частина|частка| трафіку, що викликається|спричиняє| підтримкою когерентності кеша, доводиться|припадає| на SRQ| і контроллері пам'яті, і не дає навантаження на комутатор. Крім того, використання високошвидкісного інтерфейсу HyperTransport| в Opteron і Athlon64 передбачає|припускає| як з'єднання|сполуку| процесорів через HyperTransport| з|із| підтримкою когерентності кеша в багатопроцесорних серверах, так і пряме — без північного і південного мостів — під'єднування через HyperTransport| мостів шин PCI-X/PCI-Express, що також підвищує продуктивність. Сумарна пропускна спроможність вводу/виводу для 8-процесорних систем на базі Opteron| 8xx| досягає 30,4 Гбайт/с, для двопроцесорних систем на базі Opteron| 2xx| — 22,4 Гбайт/с. З точки зору|з погляду| архітектури пам'яті побудова|шикування| серверів з|із| Opteron| відповідає архітектурі ccNUMA|, хоч доки|поки| і з|із| невеликим, до 8, числом процесорів.

Інші переваги Opteron|, наприклад, низькі величини затримок при роботі з|із| ієрархією пам'яті. Так, затримка Opteron| при вибірці з|із| кеша даних першого рівня дорівнює трьом тактам, і є|наявний| два порти читання, що дають можливість|спроможність| двох одночасних операцій. У Xeon| DP| ця затримка дорівнює 4 тактам, а порт читання лише|тільки| один. 



1.3 AMD Phenom

AMD Phenom (скорочено від слова phenomenon (феномен, незвичне явище) -   багатоядерний центральний процесор від компанії AMD. Створений для персональних комп'ютерів. Має: два, три або чотири ядра. Базується на архітектурі К10.  Триядерні версії (кодова назва Toliman) Phenom відносяться до серії 8000 і чотирьохядерні (кодова назва Agena) до AMD Phenom X4 9000.

AMD вважають, що чотирьохядерні Phenom-и були першими «істинними» чотирьохядерними процесорами, тому що саме вони, по суті, являються монолітним багатоядерним чіпом (всі ядра розташовані на тій же підложці кремнію), на відміну від серії процесорівIntel Core 2 Quad, які за дизайном являються мультикристально-модульними процесорами. Процесори розроблені для платформи Socket AM2+.[2]

Ці процесори покоління AMD| K10|, на жаль, не здобули популярності серед користувачів із-за проблем, що мали місце при їх появі. Перед офіційним випуском Phenom, була виявлена помилка в буфер асоціативної трансляції (TLB), яка могла спричинити блокування системи в різних випадках. Процесори Phenom аж до степінгу «B2» і «BA» схильні до цієї помилки. Якщо в BIOS і в програмному забезпеченні відключч\ити TLB, то це, як правило, призводить до втрати швидкодії порядку 10%. Процесори Phenom степінгу «В3» (моделі з номерами «xx50») були представлені 27 березня 2008 року, і були позбавлені помилки TLB

З технічної точки зору архітектура процесорів AMD| Phenom| X4/X3 (кодове ім'я Agena/Toliman) стала логічним продовженням ідей, закладених в дуже успішні Athlon| 64 і Athlon| 64 X2|.

Серед ключових|джерельних| особливостей виділимо наступні|такі| пункти.

Шина HyperTransport| була розроблена для Athlon| 64 і благополучно перекочувала до нового покоління - HyperTransport| 3.0. Вона використовується для обміну даними процесора зі|із| всією останньою периферією. Для Phenom| X3| її частота складає 1800 Мгц (для порівняння: у попередньому поколінні це значення було 1000 Мгц, а максимальна для топовых| моделей Phenom| X4| – 2000 Мгц). Хоча це поліпшення|покращання| має сенс лише|тільки| для серверних версій процесорів, призначених для багатопроцесорних конфігурацій. Настільним комп'ютерам з лишком вистачає частоти HT| в 1 ГГц.

Вбудований | контроллер пам'яті, по суті, кардинальним чином не змінився, оскільки|тому що| повністю|цілком| виправдовує себе. За швидкістю доступу до оперативної пам'яті процесори AMD| випереджали Intel| Pentium4| і навіть Core| 2 Duo|. Інженери компанії лише допрацювали|доопрацьовували| контроллер, зменшили затримки звернення до модулів ОЗУ, додали|добавляли| новий режим роботи – Unganged| (так званий "розпарений" режим), який, на відміну від звичайного|звичного| режиму Ganged| ("спареного"), має два як би незалежних 64-бітових каналу пам'яті. Тоді як класична двухканальність| – це один канал, але|та| подвоєної ширини - 128 біт. Підтримується пам'ять з|із| швидкістю аж до DDR2-1066|. Додана|добавляти| також підтримка пам'яті DDR3|, правда, вона не задіяна до цих пір, і практичну реалізацію знайде лише|тільки| в нових процесорах - Phenom| II.

Внутрішня кеш-пам'ять L1| і L2| за логікою роботи залишилася колишньою: вона ексклюзивна, тобто дані з|із| L1| не дублюються в L2|, і їх об'єм|обсяг| можна підсумовувати. Розміри цих кешів складають 128 і 512 KB| відповідно, як і у більшості процесорів попереднього покоління. З|із| удосконалень відзначимо розширення шини обміну ядра процесора з|із| обома|обидва| кешами з 64 до 128 біт.

Проте|однак| найзначнішим нововведенням слід вважати|лічити| появу внутрішньої кеш-пам'яті L3| розміром 2 MB|, також ексклюзивною, що є|з'являється|, по відношенню до L1| і L2|. Ця кеш-пам'ять загальна|спільна| для всіх трьох ядер Phenom| X3| (або чотири – для Phenom| X4|), а L1| і L2| є|наявний| в кожному окремому ядрі. Таким чином, сумарний об'єм|обсяг| кеша другого і третього рівнів для всіх процесорів Phenom| X4| складає 4 MB| і 3.5 MB| – для AMD| Phenom| X3|.

Виконавчі блоки ядра процесора для роботи з|із| дійсними числами залишилися в тій же кількості, що і в|у| Athlon| 64, але|та| збільшили свою розрядність удвічі|вдвічі| – до 128 біт.

Набор інструкцій SSE4A| для швидкого виконання певних операцій, що використовуються для прискорення або кодування відео і інших завдань|задач|, тепер несумісний з|із| аналогічними інструкціями Intel|. Це може створити певні труднощі для програмістів і привести до появи неоптимізованого ПО для однієї з платформ (із зрозумілих причин їй швидше|скоріше| стане AMD|).

Інші оптимізації. Серед них можна виділити вдосконалену технологію енергозбереження Cool’n’Quiet| 2.0, що тепер управляє окремо і незалежно всіма ядрами процесора і шиною HyperTransport|, знижуючи частоту і напругу|напруження| живлення|харчування| кожного з названих|накликати| компонентів в разі|у разі| їх простою або навіть повністю|цілком| відключаючи незадіяні блоки ядра процесора. Сюди додамо|добавлятимемо| і покращувану|поліпшувати| технологію віртуалізації AMD| Virtualization| (AMD-V|).

Всі перераховані і деякі інші нововведення забезпечують, за словами представників AMD|, підвищення продуктивності кожного ядра Phenom| на 20 -25% в порівнянні з поколінням Athlon| 64 при рівних тактових частотах. Що ж, в цьому у нас ще буде можливість|спроможність| переконатися.

Основним і, мабуть, єдиною відмінністю|відзнакою| процесора Phenom| X3| від Phenom| X4| є кількість задіяних ядер. Блок-схеми цих двох процесорів представлені на

Рис. 1.2 і Рис. 1.3



Рис. 1.2 AMD| Phenom| X4|



Рис. 1.3 AMD| Phenom| X3|

Як бачимо, обоє|обидва| процесора дуже схожі. Окрім|крім| загального|спільного| числа обчислювальних ядер (і, відповідно, внутрішніх L1-| і L2-кэшей|, оскільки|тому що| вони фізично і логічно є внутрішньою частиною|часткою| кожного обчислювального ядра), відмінностей|відзнак| немає. Адже  об'єднання відразу чотирьох ядер на одному кристалі, на відміну від Intel| Core| 2 Quad|, об'єднуючих в одному процесорі два окремі двоядерні кристали, одночасно є і його недоліком|нестачею|. Кристал з|із| чотирма ядрами в рамках|у рамках| 65-нм| технології виявився занадто складним і великим. Поза сумнівом|безсумнівно|, вірогідність|ймовірність| виробничого браку|шлюбу| в одному з обчислювальних ядер при виготовленні такого кристала набагато вище, ніж у конкурента. Тим більше що AMD| все ж |все же таки|помітно відстає в технологічному плані від Intel|. Тому поява Phenom| X3| багато в чому обумовлена необхідністю якось використовувати кристали Phenom| X4| з|із| технологічним браком|шлюбом| в одному з обчислювальних ядер. Тобто|цебто| Phenom| X3| – це не що інше, як Phenom| X4| з|із| одним відключеним ядром.







Рис. 1.4 Структура процессора AMD| Phenom| X3

Поважно відмітити|помітити|, що при відключенні четвертого ядра об'єм|обсяг| кеш-пам'яті третього рівня L3| залишився таким же, як і в|у| Phenom| X4|, і складає 2 MB|. У деяких умовах ця особливість може навіть дати перевагу Phenom| X3| над його старшим "братом" при однакових тактових частотах. Допустимо, процесор працює з|із| додатком|застосуванням|, що ефективно використовує лише|тільки| три ядра. В цьому випадку одне ядро Phenom| X4| простоюватиме, тоді як всі ядра Phenom| X3| задіяні. Все б добре, але|та| на одне ядро Phenom| X4| доводиться|припадає| лише чверть|четвертина| 2 MB| кеш-пам'яті L3|, а Phenom| X3| – третина, тобто|цебто| трохи більше. Це і може трохи збільшити продуктивність останнього. 



1.4 AMD Turion

Turion X2 Ultra (кодове ім'я Griffin) є першим із сімейства процесорів AMD виключно для мобільної платформи, заснованої на Athlon 64 (K8 Редакція G) архітектури з деякими конкретними архітектурних удосконалень за аналогією з нинішньою Phenom процесорів, спрямованих на зниження споживання потужності і збільшення терміну служби батарей . Ultra процесор Turion була випущена як частина " Пума "мобільної платформи в червні 2008 року. 

Turion X2 Ultra є двоядерний процесор для виготовлених на 65-нм технології з використанням 300 мм пластин КНІ. Вона підтримує DDR2-800 SO-DIMM і можливості DRAM Prefetcher для підвищення продуктивності і мобільних підвищеної північний міст (контролер пам'яті, контролер HyperTransport і координатний комутатор). Кожне ядро процесора входить 1 Мб кеша L2 на загальну суму 2 Мбайт кешу L2 на весь процесор. Кеш L2  знаходиться на поточному Turion 64 X2. Тактова частота коливається від 2,0 ГГц до 2,4 ГГц, а теплової енергії дизайн (TDP) в діапазоні від 32 Вт до 35 Вт.]

Нова функція X2 Ultra процесор Turion є те, що він реалізує три напруги площинах: одна для північного мосту і один для кожного ядра.  Це, поряд з кількома фазами петлі (PLL), дозволяє змінювати основні напруги, і частоту незалежно від інших основних і незалежно від північного мосту. Дійсно, протягом декількох мікросекунд,  процесор може переключитися на один з 8 рівнів частоти і один з 5 рівнів напруги. Змінюючи частоту і напругу під час роботи, процесор може адаптуватися до різних навантаження і знизити споживання енергії. Він може працювати як низький, як 250 МГц, для збереження контролю в енерговикористанні. 

Він також реалізує теплові датчики на основі комплексного SMBUS (SB-TSI) інтерфейс (замінює і виключає теплової схеми чіп монітор через SMBUS в його попередники) з додатковим сигналом, посланим з вбудованих контролера до процессора і пам'яті для зниження температури. 

Turion X2 Ultra процесор буде ділитися на той же сокет S1, як і його попередник ( Turion 64 X2 ), але не буде мати ту ж розкладку. 

Зважаючи на вищевказані заходи по архітектурі ядра були мінімально змінені  і засновані на K8, а не K10 мікроархітектури. Це робить більш імовірним, що Turion Ultra будуть уникати труднощі масштабування тактової частоти, присутньої в продукції AMD K10. 

Turion II Ultra (кодове ім'я Каспію) є мобільною версією архітектури K10.5, відомий також своїм настільним варіантом Regor. Це двоядерний процесор, з тактовою частотою 2,4 ГГц до 2,6 ГГц, 2 Мб кеша L2 (1 МБ на кожне ядро), HyperTransport на 3,6 GT / с і 128-бітний FPU. Він підтримує TDP 35W від від свого попередника Turion X2 Ultra (кодове ім'я Griffin). 

Turion II збігається з Turion Ultra II, за винятком того Turion II кошти лише 1 МБ кешу L2 (512 КБ на кожне ядро), і більш низькі тактові частоти від 2,2 ГГц до 2,3 ГГц.

Характеристики

AMD Turion 64 X2

Кодове названня

Taylor, Trinidad

Архітектура

AMD64

Сокет

S1, 638 контактов

Інтерфейс

HyperTransport (HT800)

Техпроцесс

90 нм SOI

Контролер памяті

Двохканальний DDR2-667

Число ядер

2

Кеш L1

64 кбайт даних, 64 кбайт інструкції на ядро

Кеш L2

512 кбайт на ядро

Тактова частота

1,6 - 2,0 ГГц

Площа ядра

183 мм²

Число транзисторів

154 млн.

Рабоча напруга

0,8 - 1,1 В

Тепловой пакет (TDP)

31, 33, 35 Вт

Функції енергозбереження

PowerNow!

Набір інструкцій

MMX, E3DNow!, SSE, SSE2, SSE3, NX-Bit, Pacifica VT

Таблиця 1. Характеристики AMD Turion









































































		ЗАСОБИ МОВ С#, ADA ДЛЯ ПРОГРАМУВАННЯ ПОТОКІВ



2.1 Вирішення завдання   синхронізації в мові С#

C#| підтримує паралельне виконання коду через багатопоточність. Потік – це незалежний шлях|колія| виконання, здатний|здібна| виконуватися одночасно з іншими потоками.

Програма на C#| запускається як єдиний потік, автоматично створюваний CLR| і операційною системою (“головний|чільний|” потік), і стає багатопотоковою за допомогою створення|створіння| додаткових потоків. Наприклад:

using| System|;

using System.Threading;

clas|s ThreadTes|t 

{

  static| void| Main|()

  {

    Thread| t = new| Thread|(WRITEY|);

    t.Start();            

    while| (true|) 

      Console|.Write("x"); |

  }

 

  static| void| WRITEY|() 

  {

    while| (true|) 

      Console|.Write("y|у|");

}

          У головному потоці створюється новий потік t, виконуючий метод, який безперервно друкує символ ‘ y’. Одночасно головний потік безперервно друкує символ ‘ x’.

   CLR призначає кожному потоку свій стек, так що локальні змінні зберігаються окремо. У наступному прикладі ми визначаємо метод із локальною змінною, а потім виконуємо його одночасно в головному і cтвореному потоках:

static| void| Main|() 

{

  new| Thread|(Go|).Start();      

  Go|();                         }

 

static| void| Go|() 

{

  // Визначаємо і використовуємо локальну змінну 'cycles|'

  for| (int| cycles| = 0; cycles| < 5; cycles++|)

    Console|.Write('?');

}



Управління багатопоточністю здійснює планувальник потоків, цю функцію CLR| зазвичай|звично| делегує операційній системі. Планувальник потоків гарантує, що активним потокам виділяється відповідний час на виконання, а потоки, чекаючі або блоковані, наприклад|приміром|, на чеканні|очікуванні| ексклюзивного блокування, або призначеного для користувача введення – не споживають часу CPU|.

На однопроцесорних комп'ютерах планувальник потоків використовує квантування часу – швидке перемикання між виконанням кожного з активних потоків. Це наводить до непередбачуваної поведінки, як в найпершому прикладі, де кожна послідовність символів ‘ X’ і ‘ Y’ відповідає кванту часу, виділеному потоку. У Windows XP типове значення кванта часу – десятки мілісекунд – вибрано як набагато більше, ніж витрати CPU на перемикання контексту між потоками (декілька мікросекунд).

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

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

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

У деяких аспектах потоки і процеси схожі – наприклад, час розділяється між процесами, що виконуються на одному комп'ютері, так само, як між потоками одного C#-додатком|. Ключова|джерельна| відмінність полягає в тому, що процеси повністю|цілком| ізольовані один від одного. Потоки розділяють пам'ять з|із| іншими потоками цього ж застосування. Завдяки цьому один потік може поставляти дані у фоновому режимі, а інший – показувати ці дані у міру їх вступу|надходження|.

Типове застосування з багатопоточністю виконує тривалі обчислення у фоновому режимі. Головний потік продовжує виконання, тоді як робочий потік виконує фонове завдання. У додатках Windows Forms, коли головний потік зайнятий тривалими обчисленнями, він не може обробляти повідомлення клавіатури і миші, і додаток перестає відгукуватися. З цієї причини слід запускати що віднімають багато часу завдання в робочому потоці, навіть якщо головний потік в цей час демонструє користувачеві модальний діалог з написом “Працюю... Будь ласка, чекайте”, оскільки програма не може перейти до наступної операції, поки не закінчена поточна. Таке рішення гарантує, що додаток не буде помічений операційною системою як що “Не відповідає”. В разі|у разі| додатків|застосувань| без UI|, наприклад, служб Windows|, багатопоточність має сенс, якщо виконуване завдання|задача| може зайняти|позичати| багато часу, оскільки|тому що| потрібне чекання|очікування| відповіді від іншого комп'ютера (сервера додатків|застосувань|, сервера баз даних або клієнта). Запуск такого завдання|задачі| в окремому робочому потоці означає, що головний|чільний| потік негайно звільняється|визволяє| для інших завдань|задач|.

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

C#-додаток можна зробити багатопотоковим двома способами: або явно створюючи додаткові потоки і управляючи ними, або використовуючи можливості неявного створення потоків .NET Framework – BackgroundWorker, пул потоків, потоковий таймер, Remoting-сервер, Web-службы або додаток ASP.NET. У двох останніх випадках альтернативи багатопоточності не існує. Однопоточний web-сервер не просто поганий, він просто неможливий. На щастя, в разі серверів додатків, що не зберігають стан (stateless), багатопоточність реалізується зазвичай досить просто, складнощі можливі хіба що в синхронізації доступу до даних в статичних змінних.

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

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

Створення|створіння| і запуск потоків С#

Для створення потоків використовується конструктор класу Thread, що приймає як параметр делегат типа ThreadStart, вказуючий метод, який потрібно виконати. Делегат ThreadStart визначається так:



public delegate void ThreadStart();

Виклик методу Start починає виконання потоку. Потік триває до виходу з виконуваного методу. Ось приклад, що використовує повний синтаксис C# для створення делегата ThreadStart:

																class| ThreadTest| 

																{

																  static| void| Main|() 

																  {

																    Thread| t = new| Thread|(new| ThreadStart|(Go|));

																    t.Start();   // Виконати Go|() у новому потоці.

																    Go|();        // Одночасно запустити Go|() у головному|чільному| потоці.

																  }

																

  static void Go() { Console.WriteLine("hello!"); }



В даному прикладі потік виконує метод Go() одночасно з головним потоком. Результат – два майже одночасних «hello»:

																hello|! hello|!

																

2.2  Засоби|кошти| синхронізації в мові С#

У наступних|таких| таблицях приведена інформація про інструменти С# для координації (синхронізації) потоків:



Конструкція



Призначення



Sleep



Блокування на вказаний час



Join



Чекання закінчення іншого потоку



Табл. 2.1 Прості методи блокування



Конструкція



Призначення



Доступна з інших процесів?



Швидкість



Lock



Гарантує, що лише один потік може дістати доступ до ресурсу або секції коди.



немає



швидко



Mutex



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



так



середня



Semaphore



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



так



середня



Табл. 2.2 Блокувальні конструкції



Конструкція



Призначення



Доступна з інших процесів



Швидкість



EventWaitHandle



Дозволяє потоку чекати сигналу від іншого потоку.



так



середньо



Wait and Pulse



Дозволяє потоку чекати, поки не виконається задана умова блокування.



немає



середньо



Табл. 2.3 Сигнальні конструкції



Конструкція



Призначення



Доступна з інших процесів



Швидкість



Interlocked



Виконання простих не блокуючих атомарних операцій.



Так – через пам'ять, що розділяється



дуже швидко



volatile



Для безпечного не блокуючого доступу до полів.



Так – через пам'ять, що розділяється



дуже швидко



Табл. 2.4 Не блокуючі конструкції синхронізації



Блокування

Коли потік зупинений в результаті використання конструкцій, перерахованих в наведених вище таблицях, говорять, що він блокований. Будучи блокованим, потік негайно перестає отримувати час CPU, встановлює властивість ThreadState в WaitSleepJoin і залишається в такому стані, поки не розблоковується. Розблокування може статися в наступних чотирьох випадках (кнопка виключення живлення не вважається!):

виконається умова розблокування;

витече|закінчуватиметься| таймаут операції (якщо він був заданий);

по перериванню через Thread.Interrupt;

по аварійному завершенню через Thread.Abort.

Потік не вважається блокованим, якщо його виконання припинене методом Suspend, що не рекомендується.

Виклик Thread.Sleep блокує поточний потік на вказаний час (або до переривання):

																static| void| Main|()

																{

																  Thread|.Sleep(0);   |

																  Thread|.Sleep(1000);                   

																  Thread|.Sleep(TimeSpan|.FromHours(1));  

																  Thread|.Sleep(Timeout|.Infinite);       

}

Якщо бути точнішим, Thread.Sleep відпускає CPU і повідомляє, що потоку не повинен виділятися час у вказаний період. Thread.Sleep(0) відпускає CPU для виділення одного кванта часу наступному потоку в черзі на виконання.

Унікальність Thread.Sleep серед інших методів блокування в тому, що він припиняє прокачування повідомлень Windows в додатках Windows Forms або COM-окружении потоку в однопоточному апартаменті. Через це тривале блокування головного (UI) потоку додатка Windows Forms наводить до того що додаток перестає відгукуватися – і отже, використання Thread.Sleep потрібно уникати незалежно від того, чи дійсно прокачування черги повідомлень технічно припинене. У старому COM-среде ситуація складніша, там інколи може бути бажане блокування за допомогою Sleep з одночасним прокачуванням черги повідомлень. 

Клас Thread також надає метод SpinWait, який не відмовляється від часу CPU, а навпаки, завантажує процесор в циклі на задану кількість ітерацій. 50 ітерацій еквівалентні паузі приблизно в мікросекунду, хоча це залежить від швидкості і завантаження CPU. Технічно SpinWait – не блокуючий метод: ThreadState такого потоку не встановлюється в WaitSleepJoin, і потік не може бути перерваний з іншого потоку. SpinWait рідко використовується – його головне вживання це чекання ресурсу, який повинен звільниться дуже скоро (у перебігу мікросекунд) без виклику Sleep і витрати процесорного часу на перемикання потоку. Проте ця методика вигідна лише на багатопроцесорних комп'ютерах, на однопроцесорному комп'ютері в ресурсу немає жодного шансу звільнитися, поки чекаючий на SpinWait потік не розтратить залишок кванта часу, а значить, необхідний результат недосяжний спочатку. А часті або тривалі виклики SpinWait даремно розтрачує час CPU.

Чекання|очікування| завершення потоку

Потік можна заблокувати до завершення іншого потоку викликом методу Join:

																class| JoinDemo| 

																{

																  static| void| Main|() 

																  {

																    Thread| t = new| Thread|(delegate|() { Console|.ReadLine(); });

																    t.Start();

																    t.Join();    // чекати, поки|доки| потік не завершиться

																    Console|.WriteLine("Thread| t's| ReadLine| complete|!");

																  }

}

Метод Join може також приймати як аргумент timeout - в мілісекундах або як TimeSpan. Якщо вказаний час витік, а потік не завершився, Join повертає false. Join з timeout функціонує як Sleep – фактично наступні два рядки коди наводять до однакового результату:

																Thread|.Sleep(1000);

Thread.CurrentThread.Join(1000);

Блокування і потокова безпека

Блокування забезпечує монопольний доступ і використовується, аби|щоб| забезпечити виконання однієї секції коди лише|тільки| одним потоком одночасно. Для прикладу|зразка| розглянемо|розглядуватимемо| наступний|слідуючий| клас:

																class| ThreadUnsafe| 

																{

																  static| int| val1|, val2|;

																 

																  static| void| Go|() 

																  {

																    if| (val2| != 0)

																      Console|.WriteLine(val1| / val2|);

																    val2| = 0;

																  }

																}

Він не є потокобезпечним: якби метод Go викликався двома потоками одночасно, можна було б отримати помилку ділення на 0, оскільки змінна val2 могла бути встановлена в 0 в одному потоці, у той час коли інший потік знаходився б між if і Console.WriteLine.

От як за допомогою блокування можна вирішити цю проблему:

																

																

																class| ThreadSafe| 

																{

																  static| object| locker| = new| object|();

																  static| int| val1|, val2|;

																 

																  static| void| Go|() 

																  {

																    lock| (locker|) 

																    {

																      if| (val2| != 0)

																        Console|.WriteLine(val1| / val2|);

																

																      val2| = 0;

																    }

																  }

																}

Лише один потік може одноразово заблокувати об'єкт синхронізації (в даному випадку locker), а всі інші конкуруючі потоки будуть припинені, поки блокування не буде знято. Якщо за блокування борються декілька потоків, вони ставляться в чергу чекання – "Ready queue" – і обслуговуються, як тільки це стає можливим, за принципом “першим прийшов – першим обслужений”. Ексклюзивне блокування, як вже говорилося, забезпечує послідовний доступ до того, що вона захищає, так що виконувані потоки вже не можуть накластися один на одного. В даному випадку ми захистили логіку усередині методу Go, так само, як і поля val1 і val2.

Потік, заблокований на час чекання звільнення блокування, має властивість ThreadState, встановлену в WaitSleepJoin. Пізніше ми обговоримо, як потік, заблокований в такому стані, може бути примусово звільнений з іншого потоку викликом методів Interrupt або Abort. Це досить потужна можливість, використовувана зазвичай для завершення робочого потоку.

Оператор lock мови C# фактично є синтаксичним скороченням для викликів методів Monitor.Enter і Monitor.Exit в рамках блоків try-finally. Ось в що фактично розвертається реалізація методу Go з попереднього прикладу:

																Monitor|.Enter(locker|);

																try| 

																{

																  if| (val2| != 0)

																    Console|.WriteLine(val1| / val2|);

																

																  val2| = 0;

																}

																

finally { Monitor.Exit(locker); }

Виклик Monitor.Exit без попереднього виклику Monitor.Enter для того ж об'єкту синхронізації викличе виключення.

Monitor також надає метод TryEnter, що дозволяє задати час чекання в мілісекундах або у вигляді TimeSpan. Метод повертає true, якщо блокування було отримане, і false, якщо блокування не було отримане за заданий час. TryEnter може також бути викликаний без параметрів і в цьому випадку повертає управління негайно.

При неправильному використанні в блокування можуть бути і негативні наслідки – зменшення можливості паралельного виконання потоків, взаимоблокировки, гонки блокувань. Можливості для паралельного виконання зменшуються, коли надто багато коди поміщено в конструкцію lock, заставляючи інші потоки простоювати весь час, поки цей код виконується. Взаємоблокування настає, коли кожен з двох потоків чекає на блокуванні іншого потоку і, таким чином, ні той, ні інший не може рушити далі. Гонкою блокувань називається ситуація, коли будь-який з двох потоків може першим отримати блокування, проте програма ламається, якщо першим це зробить “неправильний” потік.

Взаємоблокування – загальний|спільний| синдром багатьох об'єктів синхронізації. Хороше|добре| правило, що допомагає уникати взаємоблокуваннь |, полягає в тому, аби|щоб| починати з блокування мінімальної кількості об'єктів, і збільшувати міру|ступінь| деталізації блокувань, коли розмір коди в блокуванні надмірно збільшується.

Заблокований потік може бути передчасно розблокований двома шляхами:

За допомогою Thread.Interrupt.

За допомогою Thread.Abort.

Це повинно бути зроблено з|із| іншого потоку; чекаючий потік безсилий що-небудь зробити в блокованому стані|статку|.

Interrupt|

Виклик Interrupt для блокованого потоку примусово звільняє його з генерацією виключення ThreadInterruptedException, як показано в наступному прикладі:



																class| Program| 

																{

																  static| void| Main|() 

																  {

																    Thread| t = new| Thread|(delegate|() 

																      {

																        try| 

																        {

																          Thread|.Sleep(Timeout|.Infinite);

																        }

																        catch|(ThreadInterruptedException|) 

																        {

																          Console|.Write("Forcibly| ");

																        }

																

																        Console|.WriteLine("Woken|!");

																      });

																 

																    t.Start();

																    t.Interrupt();

																  }

}

Wait| Handles|

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

У Win32 API є багатий набір конструкцій синхронізації, і вони доступні в .NET Framework у вигляді класів EventWaitHandle, Mutex і Semaphore. Деякі з них практичний за інших: Mutex, наприклад, здебільше дублює можливості lock, тоді як EventWaitHandle надає унікальні можливості сигналізації.

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

EventWaitHandle має два похідних класу – AutoResetEvent і ManualResetEvent (що не мають жодного відношення до подій і делегатів C#). Обом класам доступні всі функціональні можливості базового класу, єдина відмінність полягає у виклику конструктора базового класу з різними параметрами.

У частині продуктивності, все WaitHandle зазвичай виконуються в районі декількох мікросекунд. Це рідко має значення з врахуванням контексту, в якому вони застосовуються.

AutoResetEvent дуже схожий на турнікет – один квиток дозволяє пройти одній людині. Приставка “auto” в назві відноситься до того факту, що відкритий турнікет автоматично закривається або “скидається” після того, як дозволяє кому-небудь пройти. Потік блокується в турнікета викликом WaitOne (чекати (wait) в даного (one) турнікета, поки він не відкриється), а квиток вставляється викликом методу Set. Якщо декілька потоків викликають WaitOne, за турнікетом утворюється черга. Квиток може “вставити” будь-який потік – іншими словами, будь-який (неблокований) потік, що має доступ до об'єкту AutoResetEvent, може викликати Set, аби пропустити один блокований потік.

Якщо Set викликається, коли немає чекаючих потоків, хэндл знаходитиметься у відкритому стані, поки який-небудь потік не викличе WaitOne. Ця особливість допомагає уникнути гонок між потоком, відповідним до турнікета, і потоком, що вставляє квиток (“опа, квиток вставлений на мікросекунду раніше, дуже шкода, але вам доведеться почекати ще скільки-небудь!”). Проте багатократний виклик Set для вільного турнікета не дозволяє пропустити за раз цілий натовп – зможе пройти лише один людина, всі останні квитки будуть витрачені даремно.

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

Метод Reset забезпечує закриття відкритого турнікета, без всяких чекань і блокувань.

Мьютекс забезпечує ті ж самі функціональні можливості, що і оператор lock в C#, що робить його таким, що не дуже зажадався. Єдина перевага полягає в тому, що Mutex доступний з різних процесів, забезпечуючи блокування на рівні комп'ютера, у відмінності від оператора lock, який діє лише на рівні додатка. Mutex відносно швидкий, але lock швидше в сотні разів. Здобуття мьютекса займає декілька мікросекунд, виклик lock – десятки Наносекунди (якщо не відбувається власне блокування). Метод WaitOne для Mutex отримує виняткове блокування, блокуючи потік, якщо це необхідно. Виняткове блокування може бути зняте викликом методу ReleaseMutex. Точно також як оператор lock в C#, Mutex може бути звільнений лише з того ж потоку, що його захопив.

Типове використання мьютекса| для взаємодії процесів – забезпечення можливості|спроможності| запуску лише|тільки| одного екземпляра|примірника| програми одноразово. Приклад:

																class| OneAtATimePlease| 

																{

																  static| Mutex| mutex| = new| Mutex|(false|, "oreilly|.com OneAtATimeDemo|");

																  static| void| Main|() 

																  {

																    if| (!mutex.WaitOne(TimeSpan|.FromSeconds(5), false|)) 

																    {

																      Console|.WriteLine("У системі запущений інший екземпляр|примірник| програми!");

																      return|;

																    }

																    try| 

																    {

																      Console|.WriteLine("Працюємо - натискуйте|натискайте| Enter| для виходу...");

																      Console|.ReadLine();

																    }

																    finally| { mutex|.ReleaseMutex(); }

																  }

																}

Корисна властивість Mutex – якщо додаток завершується без виклику ReleaseMutex, CLR звільняє мьютекс автоматично.

Semaphore з ємкістю, рівній одиниці, подібний Mutex або lock, за винятком того, що він не має потоку-господаря. Будь-який потік може викликати Release для Semaphore, тоді як у випадку з Mutex або lock лише потік, що захопив ресурс, може його звільнити.

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

																class| SemaphoreTest| 

																{

																  static| Semaphore| s = new| Semaphore|(3, 3);  // Available=3|; Capacity=3|

																  static| void| Main|() 

																  {

																    for| (int| i = 0; i < 10; i++|)

																      new| Thread|(Go|).Start();

																  }

																 

																  static| void| Go|() 

																  {

																    while| (true|) 

																    {

																      s.WaitOne();

																      // Лише|тільки| 3 потоки можуть знаходитися|перебувати| тут одночасно

																      Thread|.Sleep(100);

																      s.Release();

																    }

																  }

																}

																

2.3 ВИРІШЕННЯ ЗАВДАННЯ  СИНХРОНІЗАЦІЇ В МОВІ АДА

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

	Існує декілька схем синхронізації процесів :

		один процес очікує на подію в одному процесі (а);

		декілька процесів очікують на подію в одному процесі (b);

		один процес очікує на події в кількох процесах (с).

	Для вирішення завдання синхронізації, яке іноді називають синхронізацією за подіями (event synchronization), можна використовувати різні механізми синхронізації процесів, таки як семафори, події, монітори.

	Для вирішення завдання синхронізації в мові Ада95 можна застосувати механізм семафорів, а також захищені модулі.

	Застосування семафорів. Розглянемо приклад, у якому задача А чекає на подію, яку мають містити задачі В, наприклад, введення даних (змінної х). Для синхронізації процесів з уведення використовуємо семафор СігналПроПодію з початковим значенням false, яке встановлюється автоматично під час створювання семафора. Очікування події в процесі А реалізовано за допомогою операції Suspend__Until_True (СігналПроПодію), а посилання сиггалу про подію в задачі В реалізовано за допомогою операції Set     True(СігналПроПодію) .

	procedure Синхронізація is

	X : integer;  --  глобальна  змінна

	СігналПроПодію: Suspension_Object;        -- семафор

	— задача, що чекає на подію

	task A;

	task body A is

	begin

	точка очікування  події 

	Suspend_Until_True(СігналПроПодію);

	end A;

	-- задача, де  пройде  подія

	task В;

	task body В is

	begin

	get(X); -- введення даних(подія, наяку чекає А)

	Set_True(СігналПроПодію);    -- сигнал задачі А

	end В; begin

	null ;

	end Синхронізація;

Механізм семафорів запропонував математик Е.Дейкстра. У класичній інтерпретації механізм семафорів - це спеціальний захищений тип Semaphore та дві неподільні операції над змінною цього типу: P(S) і V(S). Неподільність операції означає, що її не можна переривати, поки не завершиться її виконання.

У мови Ада механізм семафорів подано у вигляді пакета Synchronous_Task_Control  в додатку Annex D: Real-Time Systems.   Пакет реалізує механізм   семафорів    таким чином.    Семафорний    тип    забезпечується    приватним    типом Suspension_object,  операції P(S)   і  V(S) реалізовані за допомогою процедур Suspend_Until_True () і SetJTrue ().  Використовується бінарний логічний семафор, тобто семафорні змінні типу   Suspension_Object   набувають значень false    і   true. Крім указаних процедур, в пакеті реалізовані допоміжні процедури SetFalseO     для   встановлення значення семафора в     false і Currentstate () для зчитування поточного значення семафора. Специфікація пакета:

package Ada.Synchronous_Task_Control is

   type Suspension_Object limited private;

rocedure Set_True(S : in out 3uspension_Object); 

procedure Set_False(S : in out Suspension_Object);

function Current_State(S : Suspension_Object) return Boolean; 

procedure Suspend_Until_True(3 : in  out Suspension_Object); private

end Ada.Synchronous_Task_Control;



Ідея   монітора, яку запропонував Б. Хансен і розвинув С. Хо ґрунтується на об'єднанні змінних, що описують спільний ресуpc, і дій, які визначають засоби доступу до спільного ресурсу. Монітор - програмний модуль, що містить змінні та процедури роботи над ними,   причому доступ до змінних можливий тільки

в процедурі.

Монітор - засіб розподілу ресурсів і взаємодії процесів Це назначення монітора реалізується за допомогою властивостей, якими наділені процедури   монітора. Характерна особливість процедур монітора - взаємне виключення ними одне одного. У будь-який момент часу може виконуватися тільки одна процедура монітора. Якщо будь-який процес викликав і виконуй процедуру монітора. то жоден процес не може виконувати будь-які процедури цього монітора. За спроби виклику іншим процесом процедури, що виконується, або іншої процедури монітора цей процес блокується і розміщується в черзі блокованих процесів доти, доки активний процес не закінчить виконання процедури монітора. Тобто в моніторі не може "знаходитись" більше одного процесу. Така властивість процедур монітора забезпечує взаємне виключення процесів. які працюють з монітором.

Загальна структура монітора:

monitor     ім'я Монітора;

--   Опис  локальних  даних

--  Опис  процедур  для  доступу  до  даних begin

--   Ініціалізація  локальних  даних end     ім'я  Монітора;

У моніторі декларуються локальні змінні (спільні змінні), які захищені монітором, і процедури монітора. Значення локальних змінних можуть бути встановлені під час створення монітора. Далі значення цих змінних можуть бути прочитані або змінені процесами тільки за допомогою процедур, визначених у моніторі.

Концепцію моніторів у новому стандарті мови Ада95 реалізовано у вигляді спеціальних програмних модулів - захищених модулів (protected units). їх призначення - розширення можливості мови для програмування паралельних процесів. зокрема, для вирішення проблеми доступу до спільних ресурсів і синхронізації процесів. Крім того, захищені модулі забезпечують підтримку різних парадигм систем реального часу, для розроблення яких мову Ада використовують в першу чергу.

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

Як і всі модулі в мові, захищені модулі складаються зі специфікації і тіла.

PROTECTED [TYPE]   імя _Захшценого_Модуля

[Дискримінант]    IS

 Опис_Захищених_Операцій

[PRIVATE]

 Опис_Захищених_Елемєнтів

END  імя_Захищєного_Модуля;

Захищені операції - це:

	захищені функції.

	захищені процедури,

	захищені входи.

Захищені   функції забезпечують доступ   тільки до читання захищених і елементів. Але дозволяють робити це одночасно всім процесам автоматичним копіюванням елементів, які зчитуються.

67

Це порушує головну властивість процедур монітора, яка дозволяє знаходитися в моніторі тільки одному процесу, але це ''порушення" дозволяє скоротити час доступу до захищених елементів і не має будь-яких наслідків, оскільки зміна даних заборонена і не виконується.

Захищені процедури забезпечують ексклюзивний доступ до захищених елементів через читання і запис.

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



















\\







			АПАРАТНИЙ КОМПЛЕКС

3.1 Компютерна система

Табл 3.1 Структура комп’ютерної системи.

Процесор:



AMD PHENOM II X4 945(3.00GHz,AM3)





1 213.00 Грн.



Материнська плата:



AMD 780V



     559 грн.



Оперативна пам'ять:



DDR II 4GB PC6400 KINGSTONE(HYNIX)





1 115,80 грн.



Жорсткий диск:



500GB SATA II 16MB(WD,SEAGATE)





470.82 грн.



Відеокарта:



onboard VGA(DVI) up to 512MB







CD:



DVD-RW





184 грн.



Звук:



6-Channel HD Audio







Корпус

ATX 400W FSP(CHIEFTEC) 4U 701

624,1





4166,72



3.2 Процесор

AMD PHENOM II X4 945(3.00GHz,AM3)

Лінійка

Phenom II X4

Сокет

AM3

Тактова частота

3000 Мгц

Частота шини

HT

Коефіцієнт множення

15

Напруга на ядрі

0.875 B

Інструкції

MMX, SSE, SSE2, SSE3, SSE4, 3DNow!

Підтримка AMD64/EM64T

є

Підтримка NX Bit

є

Підтримка Virtualization Technology

є

Ядро

Deneb

Кількість ядер

4

Техпроцесс

45 нм

Об'єм кеша L1

128 Кб

Об'єм кеша L2

2048

Об'єм кеша L3

6144

Типове тепловиділення

125 Вт

Максимальна робоча температура

62 °C

Додаткова інформація

напруга на ядрі 0.875-1.5В

Табл 3.2 Характеристика процесора.

3.3 Системна плата ASUS| M3A78-CM| 6xSATA

Socket 

AM2+

Кількість сокетів для процесора

1

Системна шина 

HyperTransport

Підтримка багатоядерних процесорів 

Є



Підтримувані процесори

 

AMD PhenomFX/Phenom/Athlon64 FX/Athlon64 X2/Athlon64/Sempron

Пам'ять 

DDR2 DIMM, 533 - 1066 Мгц

Кількість слотів пам'яті 

4

Максимальний об'єм пам'яті

8 Гб

Підтримка двоканального режиму 

є

Слоти розширення 

1xPCI-E 16x, 1xPCI-E 1x, 2xPCI

Підтримка PCI Express 2.0 

є

Ethernet 

1000 Мбіт/с

S-ATA 

кількість слотів: 6, S-ATA II, RAID: 0, 1, 10

IDE 

кількість слотів: 1, ULTRADMA 133

Звук 

7.1CH, HDA

Вбудований відеоадаптер 

Є

Роз'єм живлення процесора 

4-pin

Наявність інтерфейсів  



12xUSB 2.0, вихід S/PDIF, 1xCOM, LPT, D-Sub, DVI, Ethernet, PS/2 (клавіатура)

Роз'єми на задній панелі 



6xUSB 2.0, D-Sub, DVI, Ethernet, PS/2 (клавіатура)

Основний роз'єм живлення

24-pin

Форм-фактор 

mATX

Чіпсет 

AMD 780V

Підтримка SLI/CrossFire 

Hybrid CrossFireX

BIOS

AMI з можливістю аварійного відновлення

Табл 3.2 Характеристика системної плати.

3.4 Оперативна память

Hynix DDR2-800 4096MB PC6400 (HMP351U6AFR8C-S6)



Об'єм пам'яті

4 ГБ

Тип пам'яті

DDR2 SDRAM

Частота пам'яті

800 Мгц

Ефективна пропускна спроможність

6400 Mб/с

Схема таймінгів пам'яті

CL6



Табл 3.3 Характеристика оперативної памяті.

3.4 Жорсткий диск

Вінчестер SATA 500 GB WD WD5000AAKS 16MB 7200rpmА

Ємкість 

500 Гб 

Час включення 

11 сек

Тип підшипників 

Гідродинамічний (FDB). 

Інтерфейс 



SATA-II (Сумісно з SATA-I або SATA150 контроллерами) 

Буфер 

16 Мб 

Швидкість обертання шпинделя 

7200 оборотов/хв. 

Середній час доступу

8.9 мс (читання), 10.9 мс (запис)

Час переходу з доріжки на доріжку

2 мс 

Швидкість обміну між носієм і контроллером 

до 972 Мбіт/сек 



Рівень шуму 



28 дБ (А) в режимі чекання, 33 дБ (А) - Seek Mode, 29 дБ (А) - Seek Mode 3 

Максимальні перевантаження 



65G тривалістю 2 мс при роботі; 300G тривалістю 2 мс у вимкненому стані 

Пропускна спроможність інтерфейсу 

300 Мб/сек 



Живлення 

Від SATA коннектора живлення. 

Вжиток енергії 



8.77 Вт (чтение/запись), 8.4 Вт (у режимі чекання) 

Табл 3.4 Характеристика вінчестера.

3.5 Корпус

Корпус  ATX 400W FSP(CHIEFTEC) 4U 701

5.25" 

 4 шт

3.5" зовнішні (для FDD,CardReader) 

1шт

3.5" внутрішні (для HDD) 

5шт

Додатково 

USB 2.0 виходів - 

2шт

Audio роз`єм(мікрофон, навушники) 

2шт

Блок живлення 

ATX 450 Вт кулер 120мм (SATA) 

Розміри: 

высота*глубина*ширина (мм)  

430*480*200

Табл 3.5 Характеристика корпусу







































4    РОЗРОБКА ПРОГРАМ



4.1 Задача 

Реалізація множення матриці на матрицю у чотирьох процесорній системі із спільною пам’яттю (рис. 4.1) з  використання захищеного модуля мови Ада.

Вхідні дані:

комп’ютерна система зі спільною пам’яттю, яка включає чотири процесори і два пристрої введення-виведення (рис. 2.1);

математичне завдання: реалізації множення матриці на матрицю і вектора на матрицю    ;

де MА, МB, МC – вектори розмірності N.   

введення вектора MВ виконується в процесорі Т2, введення матриці МС виконується в процесорі Т1,  виведення результату – матриці  МА – у процесі Т1. 

Етап 1. Побудова паралельного алгоритму. Паралельний алгоритм можна подати у вигляді

                 (4.1)

де  - Н елементів матриці MB, MA.

Співвідношення (4.1) визначає дії у кожному процесорі системи під час виконання обчислень.

Спільним ресурсом у рівнянні (4.1) є  MC.









                       СПІЛЬНА ПАМ’ЯТЬ



Т1

Т2

Т3

Т4

 MA, MC

MB

Рис.4.1. Структурна схема чотирипроцесорної системи 

Етап2. Розроблення алгоритмів роботи кожного процесу.

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



Т1

Т2

Т3

Т4

1.Ввід MC.

1.Введення МB.

1. Чекати сигнал від Т1,Т2.

1.Чекати сигнал від Т1,Т2.

2.СигналT1,Т2,Т3,Т4 про закінчення введення MC.

2.СигналТ1,T2,T3, Т4 про закінчення введення МB.

2. Копія 

=.

2. Копія 

=.



3.Чекати сигнал від Т1,Т2.

3.Чекати сигнал від Т1,Т2.

3. Обчислення

*

3.Обчислення

*

4. Kопія =.

4. Копія 

=.

4. Сигнал про завершення обчислення Т1

4.Сигнал від Т1, про завершення обчислення

5. Обчислення

*

5. Обчислення

*





6.Чекати сигнал від T1,Т2,Т3,Т4 про завершення обчислення.

6.Сигнал про завершення обчислення Т1.





7.Виведення MА.







Табл.3.1. Структурна таблиця розроблення алгоритмів роботи кожного процесу.

Етап 3. Розробка структурної схеми взаємодії задач. Цей етап пов'язаний із розробкою структури захищеного модуля, за допомогою якого реалізується взаємодія задач. Захищений модуль Керування (рис 2.2) включає чотири захищені елементи: В, МС, F1, F2, а також набір захищених операцій:

		вхід Чекати 1 для синхронізації з введенням в задачах Т1, Т2;

		вхід Чекати 2 для синхронізації після завершення обчислень у задачі Т1;

		функцію Копія МС для копіювання спільного ресурсу  МС;

		процедуру Ввід МС для запису значення МС у захищений модуль;

		процедуру Сигнал 1 для сигналу про завершення обчислень у задачі Т1, Т2, Т3,T4;

		процедуру  Сигнал 2 для сигналу про завершення введення даних у задачах Т2 і Т4.

	Захищені змінні F1 F2 використовуються в бар’єрах входів Чекати 1 і Чекати 2. 

	Схема захищеного модуля представлена в Додатку А

Етап 4. Лістинг програми

Лістинг програми представлено в Додатку Б



 4.2 Задача 

 Реалізація множення матриці на матрицю у чотирьох процесорній системі із спільною пам’яттю (рис. 4.2) з  використання захищеного модуля мови Ада.

Вхідні дані:

		комп’ютерна система зі спільною пам’яттю, яка включає чотири процесори ітри пристрої введення-виведення (рис. 2.1);

		математичне завдання: реалізації множення матриці на матрицю і  на

		ще одну матрицю    ;

	де MА, МB, МC, МЕ – матриці розмірності N.   

		введення матриці MВ виконується в процесорі Т2, введення матриці МС виконується в процесорі Т1, введення матриці МE виконується в процесорі Т3,  виведення результату – матриці  МА – у процесі Т4. 

Етап 1. Побудова паралельного алгоритму. Паралельний алгоритм можна подати у вигляді

       

          (4.2)

де  - Н елементів матриці МА,MB,MC,MAA.

Співвідношення (4.2) визначає дії у кожному процесорі системи під час виконання обчислень.

Спільним ресурсом у рівнянні (4.2) є  матриця MC і потім створена матриця MАА.





СПІЛЬНА ПАМ’ЯТЬ

Т1

Т2

Т3

Т4

МC

MB

MЕ

Рис.4.2. Структурна схема чотирипроцесорної системи

MА

Етап2. Розроблення алгоритмів роботи кожного процесу.

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

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

Т1

Т2

Т3

Т4

1. Введення MC.

1.Введення МB.

1. Введення МE.

1.Чекати сигнал від Т1,Т2,Т3.

2.Сигнал T1,Т2,Т3,Т4 про закінчення введення MC.

2.Сигнал Т1,Т3,Т4 про закінчення введення МB.

2.Сигнал Т1,Т2,Т4 про закінчення введення ME.

2.Копія 

3.Чекати сигнал від T1,Т2,Т3.

3.Чекати сигнал від Т1,T2,Т3.

3.Чекати сигнал від Т1,Т2,T3.

3.Обчислення



4.Копія 

4.Копія 

4.Копія 

4.Сигнал від Т1, Т2, Т3, Т4

 про завершення обчислення.

5.Обчислення



5.Обчислення



5. Обчислення



5. Чекати сигнал від Т1,Т2,T3,Т

6. Сигнал від Т1, Т2, Т3, Т4

 про завершення обчислення.

6. Сигнал від Т1, Т2, Т3, Т4

 про завершення обчислення.

6. Сигнал від Т1, Т2, Т3, Т4

 про завершення обчислення.

6.Копія 

7. Чекати сигнал від Т1,Т2,T3,Т4.

7. Чекати сигнал від Т1,Т2,T3,Т4.

7. Чекати сигнал від Т1,Т2,T3,Т4.

7.Обчислення



8.Копія 

8.Копія 

8.Копія 

8. Сигнал Т4

 про завершення обчислення.

9. Сигнал Т4

 про завершення обчислення

9. Сигнал Т4

про завершення обчислення

8. Сигнал Т4

 про завершення обчислення

9. Вивід MA



Табл. 4.2 Структурна таблиця розроблення алгоритмів роботи кожного процесу.

Етап 3. Розробка структурної схеми взаємодії задач. Цей етап пов'язаний із розробкою структури захищеного модуля, за допомогою якого реалізується взаємодія задач. Захищений модуль Керування (рис 2.2) включає чотири захищені елементи: МE, F1, F2,F3 а також набір захищених операцій:

		вхід Чекати 1 для синхронізації з введенням в задачах Т1, Т2, Т3;

		вхід Чекати 2 для синхронізації після завершення обчислень у задачі Т1, Т2, Т3,Т4;

		вхід Чекати 3 для синхронізації після завершення обчислень у задачі Т4;

		функцію Копія MAA, Kopija ME для копіювання спільного ресурсу MAA,МС;

		процедуру Ввід МE для запису значення МE у захищений модуль;

		процедуру Сигнал 1 для сигналу про завершення обчислень у задачі Т1, Т2, Т3;

		процедуру  Сигнал 2 для сигналу про завершення введення даних у задачах Т1, Т2, Т3,Т4;

		процедуру  Сигнал 3 для сигналу про завершення введення даних у задачах Т1, Т2, Т3,Т4;

Захищені змінні F1, F2, F3 використовуються в бар’єрах входів Чекати 1, Чекати 2, Чекати 3.

		Схема захищеного модуля представлена в Додатку В

Етап 4. Лістинг програми

Лістинг програми представлено в Додатку Г



4.2 Задача 

         Реалізація cуми двох добутків матриці на матрицю у чотирьох процесорній системі із спільною пам’яттю (рис. 4.3) з  використання захищеного модуля мови Ада.

Вхідні дані:

		комп’ютерна система зі спільною пам’яттю, яка включає чотири процесори і чотири пристрої введення-виведення (рис. 2.1);

		математичне завдання: реалізації множення матриці на матрицю і вектора на матрицю    ;

	де MА, МB, МC,MO,MK – матриці розмірності N.   

		введення вектора MВ виконується в процесорі Т2, введення матриці МС виконується в процесорі Т1, введення матриці МO виконується в процесорі Т3,  введення матриці МK виконується в процесорі Т4,   виведення результату – матриці  МА – у процесі Т3. 

Етап 1. Побудова паралельного алгоритму. Паралельний алгоритм можна подати у вигляді

                 (4.3)

де  - Н елементів матриці MA.

Співвідношення (4.3) визначає дії у кожному процесорі системи під час виконання обчислень.

Спільним ресурсом у рівнянні (4.3) є  MC і MK.









СПІЛЬНА ПАМ’ЯТЬ

Т1

Т2

Т3

Т4

 MB 



MC

Рис.4.3 Структурна схема чотирипроцесорної системи

 MO, MA 



MK

Етап2. Розроблення алгоритмів роботи кожного процесу.

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

Т1

Т2

Т3

Т4

1.Ввід MB.

1.Введення МB.

1. Введення МO.

1. Введення МK.

2.Сигнал T1-T4 про закінчення введення.

2.Сигнал T1-T4 про закінчення введення.

2.Сигнал T1-T4 про закінчення введення.

2. Сигнал T1-T4 про закінчення введення.



3.Чекати сигнал від Т1-T4.

3.Чекати сигнал від Т1-T4.

3. Чекати сигнал від Т1-T4.

3. Чекати сигнал від Т1-T4.

4. Копія 



=.

4. Копія 



=.

4. Копія 



=.

4. Копія 



=.

5. Обчислення



5. Обчислення



5. Обчислення



5. Обчислення



6.Чекати сигнал від Т1-T4 про завершення обчислення.

6. Чекати сигнал від Т1-T4 про завершення обчислення.

6. Чекати сигнал від Т1-T4 про завершення обчислення.

6. Чекати сигнал від Т1-T4 про завершення обчислення.





7.Виведення MА.



Табл. 4.3 Структурна таблиця розроблення алгоритмів роботи кожного процесу.

Етап 3. Розробка структурної схеми взаємодії задач. Цей етап пов'язаний із розробкою структури захищеного модуля, за допомогою якого реалізується взаємодія задач. Захищений модуль Керування (рис 2.2) включає чотири захищені елементи:  МС,MK, F1, F2, а також набір захищених операцій:

		вхід Чекати 1 для синхронізації з введенням в задачах Т1-T4;

		вхід Чекати 2 для синхронізації після завершення обчислень у задачах Т1-T4;

		функцію Копія МС для копіювання спільного ресурсу  МС;

		функцію Копія МK для копіювання спільного ресурсу  МС;

		процедуру Ввід МС для запису значення МС у захищений модуль;

		процедуру Ввід МK для запису значення МK у захищений модуль;

		процедуру Сигнал 1 для сигналу про завершення обчислень у задачі Т1, Т2, Т3,T4;

		процедуру  Сигнал 2 для сигналу про завершення введення даних у задачах Т1, Т2, Т3,T4;

	Захищені змінні F1 F2 використовуються в бар’єрах входів Чекати 1 і Чекати 2. 

		Схема захищеного модуля представлена в Додатку Д

Етап 4. Лістинг програми

Лістинг програми представлено в Додатку Е

	

4.4 Тестування програм

Для визначення ефективності розроблених  програм було проведено дослідження, де  визначався час виконання програми паралельної обчислюваної системи. Для цього було визначено час виконання програми у паралельно обчислюваній системі із двома ядрами, а потім у паралельно обчислюваній системі, де одне ядро було відключено через диспетчер задач. Це було зроблено для кількох значень  N -  розміру матриць. N ,було рівне 100, 200, 400, 600, 800, 1000. 

Результати часу в сек. , ,  представлені в таблицях 4.4, 4.5, 4.6







1 - ядро

2 - ядра

4 - ядра

100

3

2

1

200

10

6

3

400

43

25

13

600

97

55

30

800

177

100

58

1000

288

166

110













Табл. 4.4 Тестування 





Графік відношення часу до кількості елементів 



Рис. 4.4 Графік відношення часу 











 

1 - ядро

2 - ядра

4 - ядра

100

7

4

1

200

23

12

6

400

160

98

56

600

227

129

89

800

396

207

156

1000

653

326

250

Табл. 4.5 Тестування 



Графік відношення часу до кількості елементів 



Рис. 4.5 Графік відношення часу 



















1 - ядро

2 - ядра

4 - ядра

100

5

4

2

200

20

11

8

400

76

43

30

600

189

95

67

800

341

173

117

1000

523

268

177







































Табл. 4.5 Тестування 







Графік відношення часу до кількості елементів 



Рис. 4.5 Графік відношення часу 









ВИСНОВКИ



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

  Метою бакалаврської роботи було розробити Програмно-апаратний комплекс на основі Амд-процесорів. В перших двох розділах описано AMD-багатоядерні процесори і засоби мов С# і ADA для програмування паралельних потоків.

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

Метою четвертого розділу було визначення ефективності програми. Для визначення ефективності розробленої  програми було проведено дослідження, де  визначалося час виконання паралельної програми обчислюваної системи. 












СПИСОК ВИКОРИСТАНОЇ ЛІТЕРАТУРИ

Жуков І.А., Корочкин О.В. Паралельні та розподілені обчислення. Навч. Посіб – К.: Корнійчук, 2005. – 226 с.

	Корочкин А. В. Ада95: Введение в программирование- К.:
Свит, 1999.-260 с.

 Корочкин А., Мустафа Акрам Параллеьные вычисления: Ада и Java. - Вісн. НТУУ "КГП", Інформап ка, управління та обчислювальна техніка, 1999, К.: - № 32, С   3-17.

	Языки программирования: Ада, Паскаль, Си.Сравнение и оценка/ Под ред.Н. Джехани - М.: Радио и связь, 1989. - 386 с.

	Русанова О.В. Программное обеспечение компьютерны   систем. Особенности программирования и компиляции. - К.: Корійчук, 2003.-94 с

	Троелсон Є. С# и платформа-NET. Библиотека программиста -СПб.: Питер, 2004. - 796 с.

	Эндрюс Г. Основы многопоточного, параллельного и распреде -ленного програмирования.: Пер. с англ. - М.: Изд. Дом «Виль -ямс», 2003.-512 с.

	Элементы параллельного программирования / В.А.Вальковский, В.Е.Котов, А.Г.Марчук/ Под ред. В. Е. Котова- М.: Радио и связь, 1983.-240 с.

	Бар Р. Язык Ада в проектировании систем. - М.: Мир, 1988.-ЗІ 0 с

	 Богачев К.Ю. Основы параллельного программирования.- М.: БИНОМ. Лаб. знаний, 2003. - 342 с .

 М. Кузьминский, «64-разрядные микропроцессоры AMD». Открытые системы, № 4, 2002. 

 Паралельне програмування для многопроцессорних обчислювальних систем автори: Немнюгин С., Стесик О.

































ДОДАТКИ


Додаток А

	Блок-схема роботи програми 

F2=4

F1=2

T1-T4

T1

 Ввід МC

MC,  F1,  F2

F2=F2+1

F1=F1+1

Копія МC

Чекати обчислень

2

Чекати вводу

Сигнал 1

Сигнал 2

2

		Рис. A.1  Захищений модуль  операції 



























\

Додаток Б

Лістинг програми 





--    Zaxushenuj modylj----

----------------------------------

with Ada.Text_IO,

Ada.Integer_Text_IO,Ada.Calendar;



use Ada.Text_IO,

Ada.Integer_Text_IO,Ada.Calendar;

                                       

Procedure Bakalawr1 is

P:integer:=4;

N:integer:=5000; 

H:integer:=N/P;

 t:time;	

s1,s3:day_Duration; 

s2,s4,s5:integer;    



-----Tupu-----



type Vector is array (1..N) of integer;

type Matrix is array (1..N) of Vector;



-----Zminni------



MA,MC,MB:Matrix;



----Zaxuchenuj m-----

Protected Box is

 procedure VvidMC(MCK: in Matrix);

 function Kopija1 return Matrix;

 procedure Signal1;

 procedure Signal2;

 entry Zdat1;

 entry Zdat2;     

 private

 F1:integer:=0;

 F2:integer:=0;  

end Box;

----------------------

protected body Box is





 Procedure VvidMC(MCK: in Matrix) is

  begin

   MC:=MCK;

  end VvidMC;



 function Kopija1 return Matrix is

  begin

   return MC;

  end Kopija1;



 procedure Signal1 is

  begin

   F1:=F1+1;

  end Signal1;



 procedure Signal2 is

  begin

   F2:=F2+1;

  end Signal2;



 entry Zdat1

  when F1=2 is

   begin

    null;

 end Zdat1;



 entry Zdat2

  when F2=4 is

   begin

    null;

 end Zdat2;

 

end Box;

----------------------

 procedure start is 

task T1;

task body T1 is

 MCC,MC1:Matrix;

 begin                   

  put("T1 started");

  new_line;

--vvid matruci MC-----

  for i in  1..N loop

   for j in 1..N loop

    MCC(i)(j):=1;

   end loop;

  end loop;

  Box.VvidMC(MCC);

--Signal pro zavershennja vvody--

  Box.Signal1;

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

--Kopija---

  MC1:=Box.Kopija1;

--Obchuslennja--

  for i in 1..H loop

   for j in 1..N loop 

    for k in 1..N loop

     MA(i)(j):=MA(i)(j)+MC1(k)(j);--MB(i)(k);--*MC1(k)(j);

    end loop;

   end loop;        

  end loop;  

--Signal pro zavershennja obchuslennja--

  Box.Signal2;

--Chekaje zavershennja obchuslennja inshux procesiv--

  Box.Zdat2;

--vuvid--

  for i in 1..N loop 

   for j in 1..N loop 

    put(MA(i)(j));

    put("  ");

   end loop;   

   new_line;

  end loop;

  put("  T1 Finished ");

 end T1;

 --------------------------------

task T2;

 task body T2 is

 MBB,MC2:Matrix;

 begin

  put("  T2 started ");

--vvid---------

  for i in  1..N loop

   for j in 1..N loop

    MB(i)(j):=1;

   end loop;

  end loop;

--Signal pro zavershennja vvody---

  Box.Signal1;

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

--Kopija--

  MC2:=Box.Kopija1;

---Obchuslennja--

  for i in H+1..2*H loop

   for j in 1..N loop 

    for k in 1..N loop

     MA(i)(j):=MA(i)(j)+MB(i)(k)*MC2(k)(j);

    end loop;

   end loop;        

  end loop;  

--Signal pro zavershennja obchuslennja--               

  Box.Signal2;

  put("  T2 Finished ");

 end T2;



-------------------------------------------

task T3;

 task body T3 is

 MC3:Matrix;

 begin

  put("  T3 started ");

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

---Kopija---

  MC3:=Box.Kopija1;

 ---Obchuslennja--

  for i in 2*H+1..3*H loop

   for j in 1..N loop 

    for k in 1..N loop

     MA(i)(j):=MA(i)(j)+MB(i)(k)*MC3(k)(j);

    end loop;

   end loop;        

  end loop;  

--Signal pro zavershennja obchuslennja--               

  Box.Signal2;

  put("  T3 Finished ");

 end T3;

-------------------------------------------

task T4;

 task body T4 is

 MC4:Matrix;

 begin

  put("  T4 started ");

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

---Kopija---

  MC4:=Box.Kopija1;

---Obchuslennja--

  for i in 3*H+1..N loop

   for j in 1..N loop 

    for k in 1..N loop

     MA(i)(j):=MA(i)(j)+MB(i)(k)*MC4(k)(j);

    end loop;

   end loop;        

  end loop;  

--Signal pro zavershennja obchuslennja--     

  Box.Signal2;

  put("  T4 Finished ");

 end T4;

    begin Null;

end start;         



begin

  put_line("Main");

  put("N=");

  get(N);

  t:=clock;

  s1:=Seconds(t);

  s2:=integer(s1);

  start;

  t:=clock;

  s3:=Seconds(t);

  s4:=integer(s3);

  S5:=S4-S2;  

  new_line;          

  put("Càs programu="); 

  put(s5);

end Bakalawr1;









Додаток В

Блок-схема роботи програми





T2

F3=4

F2=4

F1=3

T1-T4

T1-T4

      Ввід МE

МE, MAA,F1,  F2,  F3

Сигнал 3

2

Чекати обчислень

F3=F3+1

F2=F2+1

F1=F1+1

    Копія МE 

Чекати обчислень

2

Чекати вводу

2

Сигнал 1

Сигнал 2

2

    Копія МAA

	Рис. В.1  Захищений модуль операції 





















































Додаток Г

Лістинг програми





--    Zaxushenuj modylj----

----------------------------------

with Ada.Text_IO,

Ada.Integer_Text_IO,Ada.Calendar;



use Ada.Text_IO,

Ada.Integer_Text_IO,Ada.Calendar;

                                       

Procedure Bakalawr2 is

P:integer:=4;

N:integer:=5000;    

H:integer:=N/P;

t:time;	

s1,S3:day_Duration; 

s2,S4,S5:integer;    



-----Tupu-----



type Vector is array (1..N) of integer;

type Matrix is array (1..N) of Vector;



-----Zminni------



MA,MC,MB,ME,MAA:Matrix;



----Zaxuchenuj m-----

Protected Box is

 procedure VvidME(MEK: in Matrix);

 function Kopija1 return Matrix;

 function Kopija2 return Matrix;

 procedure Signal1;

 procedure Signal2;

 procedure Signal3;

 entry Zdat1;

 entry Zdat2;

 entry Zdat3;     

 private

  F1:integer:=0;

  F2:integer:=0;  

  F3:integer:=0;

end Box;

----------------------

protected body Box is



 

Procedure VvidME(MEK: in Matrix) is

  begin

   ME:=MEK;

  end VvidME;



 function Kopija1 return Matrix is

  begin

   return ME;

  end Kopija1;



 function Kopija2 return Matrix is

  begin

   return MAA;

  end Kopija2;



 procedure Signal1 is

  begin

   F1:=F1+1;

  end Signal1;



 procedure Signal2 is

  begin

   F2:=F2+1;

  end Signal2;



 procedure Signal3 is

  begin

   F3:=F3+1;

  end Signal3;



 entry Zdat1

  when F1=3 is

   begin

    null;

 end Zdat1;



 entry Zdat2

  when F2=4 is

   begin

    null;

 end Zdat2;



 entry Zdat3

  when F3=4 is

   begin

    null;

 end Zdat3;

 

end Box;

----------------------

procedure start is

task T1;

task body T1 is

 MCC,ME1,MA1:Matrix;

 begin                   

  put("T1 started");

  new_line;  

--vvid matruci MC-----

  for i in  1..N loop

   for j in 1..N loop

    MC(i)(j):=1;

   end loop;

  end loop;  

--Signal pro zavershennja vvody--

  Box.Signal1;

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

--Kopija---

  ME1:=Box.Kopija1;

--Obchuslennja MC*ME--

  for i in 1..H loop

   for j in 1..N loop 

    for k in 1..N loop

     MAA(i)(j):=MAA(i)(j)+MC(i)(k)*ME1(k)(j);

    end loop;

   end loop;        

  end loop; 

--Signal pro zavershennja obchuslennja--

  Box.Signal2;

--Chekaje zavershennja obchuslennja inshux procesiv--

  Box.Zdat2;

--Kopija---

  MA1:=Box.Kopija2;

--Obchuslennja MB*(MC*ME)--

  for i in 1..H loop

   for j in 1..N loop 

    for k in 1..N loop

     MA(i)(j):=MA(i)(j)+MB(i)(k)*MA1(k)(j);

    end loop;

   end loop;        

  end loop;

--Signal pro zavershennja obchuslennja--

  Box.Signal3;

  put("  T1 Finished ");

 end T1;

 --------------------------------

task T2;

 task body T2 is

 MBB,ME2,MA2:Matrix;

 begin

  put("  T2 started ");

--vvid---------

  for i in  1..N loop

   for j in 1..N loop

    MB(i)(j):=1;

   end loop;

  end loop;

--Signal pro zavershennja vvody---

  Box.Signal1;

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

--Kopija--

  ME2:=Box.Kopija1;

--Obchuslennja MC*ME--

  for i in H+1..2*H loop

   for j in 1..N loop 

    for k in 1..N loop

     MAA(i)(j):=MAA(i)(j)+MC(i)(k)*ME2(k)(j);

    end loop;

   end loop;        

  end loop;  

--Signal pro zavershennja obchuslennja--               

  Box.Signal2;

--Chekaje zavershennja obchuslennja inshux procesiv--

  Box.Zdat2;

--Kopija---

  MA2:=Box.Kopija2;

--Obchuslennja MB*(MC*ME)--

  for i in H+1..2*H loop

   for j in 1..N loop 

    for k in 1..N loop

     MA(i)(j):=MA(i)(j)+MB(i)(k)*MA2(k)(j);

    end loop;

   end loop;        

  end loop;

--Signal pro zavershennja obchuslennja--

  Box.Signal3;  

  put("  T2 Finished ");

 end T2;



-------------------------------------------

task T3;

 task body T3 is

 MEE,ME3,MA3:Matrix;

 begin

  put("  T3 started ");

--vvid---------

  for i in  1..N loop

   for j in 1..N loop

    MEE(i)(j):=1;

   end loop;

  end loop;

Box.VvidME(MEE);

--Signal pro zavershennja vvody---

  Box.Signal1;

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

---Kopija---

  ME3:=Box.Kopija1;

 --Obchuslennja MC*ME--

  for i in 2*H+1..3*H loop

   for j in 1..N loop 

    for k in 1..N loop

     MAA(i)(j):=MAA(i)(j)+MC(i)(k)*ME3(k)(j);

    end loop;

   end loop;        

  end loop; 

--Signal pro zavershennja obchuslennja--               

  Box.Signal2;

--Chekaje zavershennja obchuslennja inshux procesiv--

  Box.Zdat2;

--Kopija---

  MA3:=Box.Kopija2;

--Obchuslennja MB*(MC*ME)--

  for i in 2*H+1..3*H loop

   for j in 1..N loop 

    for k in 1..N loop

     MA(i)(j):=MA(i)(j)+MB(i)(k)*MA3(k)(j);

    end loop;

   end loop;        

  end loop;

--Signal pro zavershennja obchuslennja--

  Box.Signal3;  

  put("  T3 Finished ");

 end T3;

-------------------------------------------

task T4;

 task body T4 is

 ME4,MA4:Matrix;

 begin

  put("  T4 started ");

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

---Kopija---

  ME4:=Box.Kopija1;

--Obchuslennja MC*ME--

  for i in 3*H+1..N loop

   for j in 1..N loop 

    for k in 1..N loop

     MAA(i)(j):=MAA(i)(j)+MC(i)(k)*ME4(k)(j);

    end loop;

   end loop;        

  end loop; 

--Signal pro zavershennja obchuslennja--     

  Box.Signal2;

--Chekaje zavershennja obchuslennja inshux procesiv--

  Box.Zdat2;

--Kopija---

  MA4:=Box.Kopija2;

--Obchuslennja MB*(MC*ME)--

  for i in 3*H+1..N loop

   for j in 1..N loop 

    for k in 1..N loop

     MA(i)(j):=MA(i)(j)+MB(i)(k)*MA4(k)(j);

    end loop;

   end loop;        

  end loop;

--Signal pro zavershennja obchuslennja—

  Box.Signal3;

--Chekaje zavershennja obchuslennja inshux procesiv--

  Box.Zdat3;  

--vuvid--

for i in 1..N loop 

   for j in 1..N loop 

    put(MA(i)(j));

    put("  ");

   end loop;   

   new_line;

  end loop;  

  put("  T4 Finished ");

 end T4;

  begin Null;

end start;         





begin

put("N=");

get(N);

 put_line("Main");

   t:=clock;

  s1:=Seconds(t);

  s2:=integer(s1);

  start;

  t:=clock;

  s3:=Seconds(t);

  s4:=integer(s3);

  S5:=S4-S2;             

  put(s5);

end Bakalawr2;

































































Додаток Д

Блок-схема роботи програми



F2=4

F1=4

T1-T4

T1-T4



 Ввід МK

MC,MK,  F1,  F2

F2=F2+1

F1=F1+1

КопіяMC

Чекати обчислень

2

Чекати вводу

2

Сигнал 1

Сигнал 2

2

КопіяMK

 Ввід МC

	

	Рис. Д.1 Захищений модуль операції 

	

	

	

	

	

	

	

	

	

	

	

	

	

	

	

	

	

Додаток Е

Лістинг програми

  --    Zaxushenuj modylj----

----------------------------------

with Ada.Text_IO,

Ada.Integer_Text_IO,Ada.Calendar;



use Ada.Text_IO,

Ada.Integer_Text_IO,Ada.Calendar;

                                       

Procedure Bakalawr3 is

P:integer:=4;

N:integer:=4000;    

H:integer:=N/P;

t:time;	

s1,S3:day_Duration; 

s2,S4,S5:integer;   



-----Tupu-----



type Vector is array (1..N) of integer;

type Matrix is array (1..N) of Vector;



-----Zminni------



MA,MC,MB,MO,MK:Matrix;



----Zaxuchenuj m-----

Protected Box is

 procedure VvidMC(MCK: in Matrix);

 procedure VvidMK(MKK: in Matrix);

 function Kopija1 return Matrix;

 function Kopija2 return Matrix;

 procedure Signal1;

 procedure Signal2;

 entry Zdat1;

 entry Zdat2;     

 private

  F1:integer:=0;

  F2:integer:=0;  

end Box;

----------------------

protected body Box is





 Procedure VvidMC(MCK: in Matrix) is

  begin

   MC:=MCK;

  end VvidMC;



 

Procedure VvidMK(MKK: in Matrix) is

  begin

   MK:=MKK;

  end VvidMK;



 function Kopija1 return Matrix is

  begin

   return MC;

  end Kopija1;



 function Kopija2 return Matrix is

  begin

   return MK;

  end Kopija2;



 procedure Signal1 is

  begin

   F1:=F1+1;

  end Signal1;



 procedure Signal2 is

  begin

   F2:=F2+1;

  end Signal2;



 entry Zdat1

  when F1=4 is

   begin

    null;

 end Zdat1;



 entry Zdat2

  when F2=4 is

   begin

    null;

 end Zdat2;

 

end Box;

----------------------

     Procedure start is

task T1;

task body T1 is

 MCC,MC1,MK1:Matrix;

 begin                   

  put("T1 started");

  new_line;  

--vvid matruci MC-----

  for i in  1..N loop

   for j in 1..N loop

    MCC(i)(j):=1;

   end loop;

  end loop;  

  Box.VvidMC(MCC); 

--Signal pro zavershennja vvody--

  Box.Signal1;

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

--Kopija---

  MC1:=Box.Kopija1;

  MK1:=Box.Kopija2;

--Obchuslennja--

  for i in 1..H loop

   for j in 1..N loop 

    for k in 1..N loop

     MA(i)(j):=MA(i)(j)+MB(i)(k)*MC1(k)(j)+MO(i)(k)*MK1(k)(j);

    end loop;

   end loop;        

  end loop; 

--Signal pro zavershennja obchuslennja--

  Box.Signal2;

  put("  T1 Finished ");

 end T1;

 --------------------------------

task T2;

 task body T2 is

 MBB,MC2,MK2:Matrix;

 begin

  put("  T2 started ");

--vvid---------

  for i in  1..N loop

   for j in 1..N loop

    MB(i)(j):=1;

   end loop;

  end loop;

--Signal pro zavershennja vvody---

  Box.Signal1;

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

--Kopija--

  MC2:=Box.Kopija1;

  MK2:=Box.Kopija2;

--Obchuslennja--

  for i in H+1..2*H loop

   for j in 1..N loop 

    for k in 1..N loop

      MA(i)(j):=MA(i)(j)+MB(i)(k)*MC2(k)(j)+MO(i)(k)*MK2(k)(j);

    end loop;

   end loop;        

  end loop;  

--Signal pro zavershennja obchuslennja--               

  Box.Signal2;

  put("  T2 Finished ");

 end T2;



-------------------------------------------

task T3;

 task body T3 is

 MOO,MC3,MK3:Matrix;

 begin

  put("  T3 started ");

--vvid---------

  for i in  1..N loop

   for j in 1..N loop

    MO(i)(j):=1;

   end loop;

  end loop;

--Signal pro zavershennja vvody---

  Box.Signal1;

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

---Kopija---

  MC3:=Box.Kopija1;

  MK3:=Box.Kopija2;

 --Obchuslennja--

  for i in 2*H+1..3*H loop

   for j in 1..N loop 

    for k in 1..N loop

     MA(i)(j):=MA(i)(j)+MB(i)(k)*MC3(k)(j)+MO(i)(k)*MK3(k)(j);

    end loop;

   end loop;        

  end loop; 

--Signal pro zavershennja obchuslennja--               

  Box.Signal2;

--Chekaje zavershennja obchuslennja inshux procesiv--

  Box.Zdat2;

--vuvid--

for i in 1..N loop 

   for j in 1..N loop 

    put(MA(i)(j));

    put("  ");

   end loop;   

   new_line;

  end loop;  

  put("  T3 Finished ");

 end T3;

-------------------------------------------

task T4;

 task body T4 is

 MKK,MC4,MK4:Matrix;

 begin

  put("  T4 started ");

--vvid---------

  for i in  1..N loop

   for j in 1..N loop

    MKK(i)(j):=1;

   end loop;

  end loop;

  Box.VvidMK(MKK);

--Signal pro zavershennja vvody---

  Box.Signal1;

--Chekaje zavershennja vvody inshux danux--

  Box.Zdat1;

---Kopija---

  MC4:=Box.Kopija1;

  MK4:=Box.Kopija2;

--Obchuslennja--

  for i in 3*H+1..N loop

   for j in 1..N loop 

    for k in 1..N loop

     MA(i)(j):=MA(i)(j)+MB(i)(k)*MC4(k)(j)+MO(i)(k)*MK4(k)(j);

    end loop;

   end loop;        

  end loop; 

--Signal pro zavershennja obchuslennja--     

  Box.Signal2;

  put("  T4 Finished ");

 end T4;

begin Null;

end start;         

begin

put("N=");

get(N);

  t:=clock;

  s1:=Seconds(t);

  s2:=integer(s1);

  start;

  t:=clock;

  s3:=Seconds(t);

  s4:=integer(s3);

  S5:=S4-S2;             

  put_line("Main");

new_line;

  put("Cas=");

  put(s5);



end Bakalawr3;

	

	





Пойда В.Ю.

Вайнагій О.М.



	

УжНУ

 ІТФ  гр. КСМ



КБР.КСМ.060029.004 ПЗ

1

59



Аркуш

Літ

.

Аркушів

Дата

Підпис

Розроб.

Король І.Ю.



Корочкін О.В.

Перевір.

Н. контр.

Затверд.

№ докум.

Арк.

Зм.

Програмно-апаратний комплекс на основі Амд-процесорів Пояснювальна записка

8



4



Арк.

КБР.КСМ.060029.004 ПЗ



Дата

Підпис

№ докум.

Лист.

Зм.