Всё сдал! - помощь студентам онлайн Всё сдал! - помощь студентам онлайн

Реальная база готовых
студенческих работ

Узнайте стоимость индивидуальной работы!

Вы нашли то, что искали?

Вы нашли то, что искали?

Да, спасибо!

0%

Нет, пока не нашел

0%

Узнайте стоимость индивидуальной работы

это быстро и бесплатно

Получите скидку

Оформите заказ сейчас и получите скидку 100 руб.!


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

Тип Реферат
Предмет Информатика
Просмотров
1504
Размер файла
502 б
Поделиться

Ознакомительный фрагмент работы:

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

ЗМІСТ

ВСТУП.. 2

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

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

1.2AMD 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:wwwdoc2htmlworkbestreferat-232132-13965101163743inputБакалаврська Вайнагій Олександр.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.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.2AMD 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.2AMD| 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

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

TurionX2 Ultra є двоядерний процесор для виготовлених на 65-нм технології з використанням 300 мм пластин КНІ. Вона підтримує DDR2-800 SO-DIMM і можливості DRAMPrefetcher для підвищення продуктивності і мобільних підвищеної північний міст (контролер пам'яті, контролер 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 в його попередники) з додатковим сигналом, посланим з вбудованих контролера до процессора і пам'яті для зниження температури.

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

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

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

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

ХарактеристикиAMD Turion 64 X2
Кодове названняTaylor, Trinidad
АрхітектураAMD64
СокетS1, 638 контактов
ІнтерфейсHyperTransport (HT800)
Техпроцесс90 нм SOI
Контролер памятіДвохканальний DDR2-667
Число ядер2
Кеш L164 кбайт даних, 64 кбайт інструкції на ядро
Кеш L2512 кбайт на ядро
Тактова частота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

2 ЗАСОБИ МОВ С#, 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’ відповідає кванту часу, виділеному потоку. У WindowsXP типове значення кванта часу – десятки мілісекунд – вибрано як набагато більше, ніж витрати CPU на перемикання контексту між потоками (декілька мікросекунд).

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

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

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

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

Типове застосування з багатопоточністю виконує тривалі обчислення у фоновому режимі. Головний потік продовжує виконання, тоді як робочий потік виконує фонове завдання. У додатках WindowsForms, коли головний потік зайнятий тривалими обчисленнями, він не може обробляти повідомлення клавіатури і миші, і додаток перестає відгукуватися. З цієї причини слід запускати що віднімають багато часу завдання в робочому потоці, навіть якщо головний потік в цей час демонструє користувачеві модальний діалог з написом “Працюю... Будь ласка, чекайте”, оскільки програма не може перейти до наступної операції, поки не закінчена поточна. Таке рішення гарантує, що додаток не буде помічений операційною системою як що “Не відповідає”. В разі|у разі| додатків|застосувань| без 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 в додатках WindowsForms або COM-окружении потоку в однопоточному апартаменті. Через це тривале блокування головного (UI) потоку додатка WindowsForms наводить до того що додаток перестає відгукуватися – і отже, використання 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), а всі інші конкуруючі потоки будуть припинені, поки блокування не буде знято. Якщо за блокування борються декілька потоків, вони ставляться в чергу чекання – "Readyqueue" – і обслуговуються, як тільки це стає можливим, за принципом “першим прийшов – першим обслужений”. Ексклюзивне блокування, як вже говорилося, забезпечує послідовний доступ до того, що вона захищає, так що виконувані потоки вже не можуть накластися один на одного. В даному випадку ми захистили логіку усередині методу 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);

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

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

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

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

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

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

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

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

taskA;

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 АПАРАТНИЙ КОМПЛЕКС

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

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

Процесор:

AMD PHENOM II X4 945(3.00GHz,AM3)

1213.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 701624,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 нм
Об'єм кеша L1128 Кб
Об'єм кеша L22048
Об'єм кеша L36144
Типове тепловиділення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
BIOSAMI з можливістю аварійного відновлення

Табл 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.

Етап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. Сигнал про завершення обчислення Т14.Сигнал від Т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АА.

Етап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.

Етап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 - ядра
100321
2001063
400432513
600975530
80017710058
1000288166110

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

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

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

1 - ядро2 - ядра4 - ядра
100741
20023126
4001609856
60022712989
800396207156
1000653326250

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

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

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

1 - ядро2 - ядра4 - ядра
100542
20020118
400764330
6001899567
800341173117
1000523268177

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

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

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

ВИСНОВКИ

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ДОДАТКИ


Додаток А

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

Рис. 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;


Додаток В

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

Рис. В.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;


Додаток Д

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

Рис. Д.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;


Нет нужной работы в каталоге?

Сделайте индивидуальный заказ на нашем сервисе. Там эксперты помогают с учебой без посредников Разместите задание – сайт бесплатно отправит его исполнителя, и они предложат цены.

Цены ниже, чем в агентствах и у конкурентов

Вы работаете с экспертами напрямую. Поэтому стоимость работ приятно вас удивит

Бесплатные доработки и консультации

Исполнитель внесет нужные правки в работу по вашему требованию без доплат. Корректировки в максимально короткие сроки

Гарантируем возврат

Если работа вас не устроит – мы вернем 100% суммы заказа

Техподдержка 7 дней в неделю

Наши менеджеры всегда на связи и оперативно решат любую проблему

Строгий отбор экспертов

К работе допускаются только проверенные специалисты с высшим образованием. Проверяем диплом на оценки «хорошо» и «отлично»

1 000 +
Новых работ ежедневно
computer

Требуются доработки?
Они включены в стоимость работы

Работы выполняют эксперты в своём деле. Они ценят свою репутацию, поэтому результат выполненной работы гарантирован

avatar
Математика
История
Экономика
icon
159599
рейтинг
icon
3275
работ сдано
icon
1404
отзывов
avatar
Математика
Физика
История
icon
156450
рейтинг
icon
6068
работ сдано
icon
2737
отзывов
avatar
Химия
Экономика
Биология
icon
105734
рейтинг
icon
2110
работ сдано
icon
1318
отзывов
avatar
Высшая математика
Информатика
Геодезия
icon
62710
рейтинг
icon
1046
работ сдано
icon
598
отзывов
Отзывы студентов о нашей работе
63 457 оценок star star star star star
среднее 4.9 из 5
Тгу им. Г. Р. Державина
Реферат сделан досрочно, преподавателю понравилось, я тоже в восторге. Спасибо Татьяне за ...
star star star star star
РЭУ им.Плеханово
Альберт хороший исполнитель, сделал реферат очень быстро, вечером заказала, утром уже все ...
star star star star star
ФЭК
Маринаааа, спасибо вам огромное! Вы профессионал своего дела! Рекомендую всем ✌🏽😎
star star star star star

Последние размещённые задания

Ежедневно эксперты готовы работать над 1000 заданиями. Контролируйте процесс написания работы в режиме онлайн

Подогнать готовую курсовую под СТО

Курсовая, не знаю

Срок сдачи к 7 дек.

только что
только что

Выполнить задания

Другое, Товароведение

Срок сдачи к 6 дек.

1 минуту назад

Архитектура и организация конфигурации памяти вычислительной системы

Лабораторная, Архитектура средств вычислительной техники

Срок сдачи к 12 дек.

1 минуту назад

Организации профилактики травматизма в спортивных секциях в общеобразовательной школе

Курсовая, профилактики травматизма, медицина

Срок сдачи к 5 дек.

2 минуты назад

краткая характеристика сбербанка анализ тарифов РКО

Отчет по практике, дистанционное банковское обслуживание

Срок сдачи к 5 дек.

2 минуты назад

Исследование методов получения случайных чисел с заданным законом распределения

Лабораторная, Моделирование, математика

Срок сдачи к 10 дек.

4 минуты назад

Проектирование заготовок, получаемых литьем в песчано-глинистые формы

Лабораторная, основы технологии машиностроения

Срок сдачи к 14 дек.

4 минуты назад

2504

Презентация, ММУ одна

Срок сдачи к 7 дек.

6 минут назад

выполнить 3 задачи

Контрольная, Сопротивление материалов

Срок сдачи к 11 дек.

6 минут назад

Вам необходимо выбрать модель медиастратегии

Другое, Медиапланирование, реклама, маркетинг

Срок сдачи к 7 дек.

7 минут назад

Ответить на задания

Решение задач, Цифровизация процессов управления, информатика, программирование

Срок сдачи к 20 дек.

7 минут назад
8 минут назад

Все на фото

Курсовая, Землеустройство

Срок сдачи к 12 дек.

9 минут назад

Разработка веб-информационной системы для автоматизации складских операций компании Hoff

Диплом, Логистические системы, логистика, информатика, программирование, теория автоматического управления

Срок сдачи к 1 мар.

10 минут назад
11 минут назад

перевод текста, выполнение упражнений

Перевод с ин. языка, Немецкий язык

Срок сдачи к 7 дек.

11 минут назад
planes planes
Закажи индивидуальную работу за 1 минуту!

Размещенные на сайт контрольные, курсовые и иные категории работ (далее — Работы) и их содержимое предназначены исключительно для ознакомления, без целей коммерческого использования. Все права в отношении Работ и их содержимого принадлежат их законным правообладателям. Любое их использование возможно лишь с согласия законных правообладателей. Администрация сайта не несет ответственности за возможный вред и/или убытки, возникшие в связи с использованием Работ и их содержимого.

«Всё сдал!» — безопасный онлайн-сервис с проверенными экспертами

Используя «Свежую базу РГСР», вы принимаете пользовательское соглашение
и политику обработки персональных данных
Сайт работает по московскому времени:

Вход
Регистрация или
Не нашли, что искали?

Заполните форму и узнайте цену на индивидуальную работу!

Файлы (при наличии)

    это быстро и бесплатно