Українська
Контрольні завдання
Практичні завдання за темами курсу для перевірки знань. Кожне завдання — окрема програма.
Тема 1. Основи паралельних обчислень
- Створити консольну програму, яка запитує частку паралельного коду (від 0 до 1) і кількість процесорів, перевіряє введення та виводить прискорення й ефективність за законом Амдала і межу прискорення.
- Створити консольну програму, яка запитує послідовну частку програми та максимальну кількість процесорів і виводить таблицю масштабованого прискорення й ефективності за законом Густафсона–Барсіса для
до заданого значення. - Створити консольну програму, яка читає з клавіатури пари «кількість процесорів – виміряний час» (серед них має бути вимірювання для одного процесора) і виводить таблицю прискорення, ефективності та метрики Карпа–Флатта.
- Створити консольну програму, яка запитує бажане прискорення та частку паралельного коду і за законом Амдала визначає мінімальну кількість процесорів, потрібну для цього прискорення, або повідомляє, що воно недосяжне.
- Створити консольну програму, яка за виміряним прискоренням на
процесорах (вводяться користувачем) обчислює частку паралельного коду за законом Амдала та прогнозує прискорення для і процесорів. - Створити консольну програму, яка вимірює за допомогою
Stopwatchчас обчислення суми квадратів чисел від 1 до ( вводиться), виконує прогрівання та 7 запусків і виводить мінімум, медіану й максимум часу. - Створити консольну програму, яка вимірює час трьох етапів обробки масиву випадкових чисел заданого користувачем розміру (заповнення, сортування, підрахунок суми), виводить частку кожного етапу та прогноз прискорення за законом Амдала для 8 ядер, якщо розпаралелити сортування.
- Створити консольну програму, яка виводить звіт про апаратну та програмну конфігурацію комп’ютера: операційна система, архітектура, версія .NET, кількість логічних процесорів, доступна пам’ять, конфігурація збирання й точність таймера.
- Створити консольну програму, яка запитує час виконання задачі на одному процесорі, частку паралельного коду та кількість процесорів і виводить прогнозований час, прискорення, ефективність і вартість (процесорний час) за законом Амдала.
- Створити консольну програму, яка порівнює час обходу двовимірного масиву розміром
( вводиться) за рядками та за стовпцями (медіана 5 запусків з прогріванням) і виводить, у скільки разів один спосіб швидший за інший.
Тема 2. Процеси та потоки
- Створити консольну програму, яка запитує кількість потоків N (від 1 до 32), запускає N іменованих потоків
Thread, кожен з яких обчислює суму квадратів чисел від 1 до 1 000 000·(номер потоку), записує результат у свій елемент масиву, і післяJoinвиводить таблицю «ім’я потоку – ManagedThreadId – результат». - Створити консольну програму, яка запитує розмір масиву та кількість потоків, заповнює масив випадковими числами (фіксоване зерно), обчислює суму масиву розбиттям на N потоків і послідовно, перевіряє збіг і виводить час обох варіантів, прискорення та ефективність.
- Створити консольну програму, яка ставить у пул потоків 50 робіт (обчислення факторіала числа від 1 до 50 як
BigInteger), чекає завершення всіх робіт і виводить результати в порядку номерів та кількість різних потоків пулу, що їх виконали. - Створити консольну програму, яка запускає фоновий потік, що кожні 100 мс збільшує лічильник, доки не встановлено прапорець
volatile bool; основний потік після натискання Enter встановлює прапорець, чекає завершення потоку не довше 1 с і виводить значення лічильника та ознаку, чи завершився потік вчасно. - Створити консольну програму, яка запускає потік, що перетворює рядки з масиву на числа; виняток у потоці перехоплюється, зберігається й після
Joinвиводиться основним потоком разом з номером некоректного рядка та сумою коректних чисел. - Створити консольну програму-координатор, яка запитує кількість процесів N, запускає себе N разів із аргументами
--worker i N(дочірній процес рахує прості числа у своїй частині діапазону до 1 000 000), читає стандартний вивід кожного процесу, перевіряє коди завершення й виводить загальну кількість простих чисел і час. - Створити консольну програму, яка виводить маску спорідненості та клас пріоритету власного процесу, запитує нову маску у двійковому вигляді, перевіряє її коректність, встановлює маску й клас
BelowNormal, виконує обчислення у 4 потоках і виводить час до та після зміни маски. - Створити консольну програму, яка за допомогою
System.Threading.Timerвиводить поточний час кожні N мілісекунд (N вводиться, від 100 до 5 000), зупиняє таймер після натискання Enter і виводить кількість спрацювань та номери потоків пулу, у яких виконувався обробник. - Створити консольну програму, яка запитує межу діапазону й максимальну кількість потоків, рахує прості числа розбиттям на 1, 2, 4, … потоків і виводить таблицю «потоки – час – прискорення – ефективність» з медіаною трьох запусків і перевіркою результату.
- Створити консольну програму, яка в трьох потоках використовує
ThreadLocal<Random>із різними зернами для генерації 1 000 000 випадкових чисел кожним потоком і лічильникThreadLocal<int>зtrackAllValues, а після завершення виводить середнє значення чисел кожного потоку та значення всіх лічильників.
Тема 3. Синхронізація потоків
- Створити консольну програму, яка запитує кількість потоків і кількість збільшень на потік, виконує збільшення спільного лічильника без синхронізації, з
Interlocked.Incrementі зlock, та виводить таблицю «спосіб – отримане значення – очікуване значення – час, мс». - Створити консольну програму, яка запитує кількість потоків і діапазон цілих чисел, розбиває діапазон між потоками й знаходить максимальну суму цифр числа, оновлюючи спільний максимум CAS-циклом
Interlocked.CompareExchange. Вивести максимум, число, у якого він досягається, і перевірку з послідовним обчисленням. - Створити консольну програму з класом банківського рахунку, у якому методи
DepositіWithdraw(без переходу в мінус) захищені окремим об’єктомLock. Програма запитує кількість потоків і операцій, виконує випадкові операції та перевіряє, що кінцевий баланс дорівнює початковому плюс сума успішних операцій. - Створити консольну програму з обмеженим буфером на
Monitor.WaitіMonitor.PulseAll. Користувач вводить ємність буфера, кількість виробників, споживачів і елементів; програма виводить кількість вироблених і спожитих елементів, їхні суми та максимальну заповненість буфера. - Створити консольну програму-модель пункту видачі посилок, яка запитує кількість вікон і клієнтів, обмежує одночасне обслуговування
SemaphoreSlimз таймаутом очікування та виводить журнал подій, кількість відмов і максимальну кількість одночасно обслуговуваних клієнтів. - Створити консольну програму з довідником товарів, захищеним
ReaderWriterLockSlim. Користувач вводить кількість читачів, кількість запитів і частку записів у відсотках; програма порівнює час роботи зlockі зReaderWriterLockSlimта виводить кількість виконаних читань і записів. - Створити консольну програму, у якій користувач вводить кількість потоків-робітників. Робітники одночасно стартують за сигналом
ManualResetEventSlim, виконують роботу випадкової тривалості, а основний потік чекає їх завершення черезCountdownEvent. Вивести час старту й завершення кожного робітника. - Створити консольну програму, яка моделює перекази між рахунками в кількох потоках з наївним порядком блокування та виявляє взаємоблокування за таймаутом
Join, а потім виконує ті самі перекази з упорядкуванням блокувань за номером рахунку. Вивести результат обох варіантів і перевірку загальної суми. - Створити консольну програму, яка розв’язує задачу про обідаючих філософів для кількості філософів, введеної користувачем, із захопленням виделок за допомогою
Monitor.TryEnterз таймаутом і випадковою затримкою. Вивести кількість обідів і повторних спроб кожного філософа. - Створити консольну програму, яка запитує кількість учасників і кількість етапів змагання. На кожному етапі учасники-потоки готуються різний час і стартують одночасно через
Barrier; програма виводить час кожного учасника на етапах і підсумкову таблицю місць.
Тема 4. Потокобезпечні колекції
- Створити консольну програму, яка запитує кількість потоків (1–32) і кількість випадкових чисел, у кількох потоках рахує, скільки разів трапляється кожна остання цифра, у спільному
ConcurrentDictionary<int, long>методомAddOrUpdateта виводить таблицю «цифра – кількість» і результат перевірки послідовним підрахунком. - Створити консольну програму, яка запитує кількість виробників, споживачів і елементів, реалізує патерн «виробник – споживач» на
BlockingCollection<int>з обмеженою ємністю, коректно завершує всіх споживачів після завершення всіх виробників і виводить кількість та суму елементів кожного споживача з перевіркою загальної суми. - Створити консольну програму, яка запитує кількість рядків і ємність каналу, будує двоетапний конвеєр на обмежених каналах (генерація рядків чисел → обчислення суми рядка в двох задачах → підсумовування) та виводить загальну суму, кількість рядків і час, перевіряючи суму послідовним обчисленням.
- Створити консольну програму, яка запитує кількість потоків і операцій, у кількох потоках кладе й вилучає завдання з
ConcurrentQueue<int>лише методамиEnqueueіTryDequeueта виводить кількість доданих, вилучених і залишених завдань із перевіркою, що жодне завдання не оброблено двічі. - Створити консольну програму, яка запитує кількість потоків і ключів, у кількох потоках одночасно запитує значення «дорогої» функції для ключів через
ConcurrentDictionary<int, Lazy<long>>і виводить значення, час роботи та кількість викликів функції, яка має дорівнювати кількості ключів. - Створити консольну програму, яка запитує кількість потоків і чисел, рахує парні числа масиву в кількох потоках двома способами (лічильники в спільному масиві та локальні змінні), виконує прогрівання й медіану трьох запусків і виводить таблицю часу й прискорення для 1, 2, 4 і 8 потоків з поясненням різниці.
- Створити консольну програму, у якій кілька потоків додають введену з клавіатури кількість рядків до спільного
ImmutableList<string>черезImmutableInterlocked.Update, а потім програма виводить кількість елементів, кількість повторів перетворення та перевіряє, що список містить усі рядки. - Створити консольну програму, яка запитує ємність каналу та режим переповнення (
DropOldest,DropNewest,DropWrite), швидко записує 10 000 чисел методомTryWriteв обмежений канал із повільним споживачем і виводить кількість записаних, прочитаних і відкинутих чисел, підраховану делегатомitemDropped. - Створити консольну програму, яка запитує кількість споживачів і завдань, додає завдання в
BlockingCollection<string?>з «отруйними пігулками» (null) для завершення кожного споживача та виводить, скільки завдань обробив кожен споживач і що всі потоки завершилися. - Створити консольну програму з неблокуючим лічильником максимуму: кілька потоків (кількість вводиться) генерують випадкові числа й оновлюють спільний максимум CAS-циклом
Interlocked.CompareExchange. Програма виводить знайдений максимум, кількість невдалих спроб CAS і перевіряє максимум послідовним проходом.
Тема 5. Задачі TPL і async/await
- Створити консольну програму, яка запитує в користувача кількість задач N (1–16) і верхню межу M, розбиває діапазон 1…M на N частин, у кожній задачі
Task.Runрахує прості числа, післяTask.WhenAllвиводить кількість простих чисел у кожній частині, загальну кількість і час обчислення та перевіряє результат послідовним підрахунком. - Створити консольну програму, яка одночасно запускає три імітовані запити до служб погоди з різними випадковими затримками, виводить першу отриману відповідь за допомогою
Task.WhenAny, скасовує решту запитів токеном і виводить стани всіх задач. - Створити консольну програму, яка будує ланцюжок задач «прочитати файл → порахувати слова → записати результат у файл» за допомогою
ContinueWith, додає продовження зOnlyOnFaultedдля виведення помилки і перевіряє роботу для наявного та відсутнього файла, шлях до якого вводить користувач. - Створити консольну програму, яка запускає 5 задач, дві з яких кидають винятки різних типів, очікує їх через
Task.WhenAllу блоціtry, виводить перший виняток, перехопленийawait, і всі винятки з властивостіException, а також стан кожної задачі. - Створити консольну програму, яка обчислює суму ряду 1/k² для k від 1 до 2 мільярдів у задачі з токеном скасування, перевіряючи токен кожні 1 000 000 ітерацій. Користувач вводить таймаут у секундах (
CancelAfter); програма виводить або результат, або повідомлення про скасування з кількістю виконаних ітерацій і стан задачі. - Створити консольну програму, яка асинхронно копіює файл, шлях до якого вводить користувач, блоками по 1 МБ, виводить прогрес у відсотках через власну реалізацію
IProgress<int>і дозволяє скасувати копіювання клавішею Esc із вилученням неповної копії. - Створити консольну програму, яка асинхронно читає всі текстові файли заданої теки (
File.ReadAllTextAsync) одночасно, не більше 4 файлів водночас (SemaphoreSlim), і виводить таблицю «файл – рядків – слів» з підсумковим рядком і загальним часом. - Створити консольну програму, яка запускає локальний тестовий сервер
HttpListenerз трьома сторінками (одна відповідає із затримкою 3 с) і за допомогою одного екземпляраHttpClientодночасно завантажує сторінки з таймаутом 1 с на запит, виводячи для кожної сторінки розмір або повідомлення про таймаут. - Створити консольну програму з асинхронним генератором
IAsyncEnumerable<int>, який кожні 200 мс (PeriodicTimer) повертає випадкове число від 1 до 100. Програма перебирає числа цикломawait foreach, виводить їх і поточне середнє та зупиняється через кількість секунд, введену користувачем, через токен скасування. - Створити консольну програму з класом-імітатором, який генерує подію
Completedчерез випадковий час від 0,5 до 3 с. За допомогоюTaskCompletionSourceпрограма перетворює подію на задачу, очікує її з таймаутом 2 с (WaitAsync) і виводить результат очікування для 5 запусків.
Тема 6. Паралелізм даних і PLINQ
- Створити консольну програму, яка запитує розмір масиву
(від 10⁶ до 10⁸), заповнює його випадковими цілими числами від 0 до 999 (фіксоване зерно) і обчислює суму квадратів елементів послідовно та за допомогоюParallel.Forз локальним станом потоку (localInit,localFinally). Програма перевіряє збіг сум і виводить час обох способів та прискорення. - Створити консольну програму, яка для масиву з
дійсних чисел (розмір вводить користувач) обчислює середнє значення й дисперсію за допомогоюParallel.ForEachзPartitioner.Create(0, n, rangeSize), де розмір діапазону також вводить користувач, перевіряє результат послідовним обчисленням і виводить кількість діапазонів, результат і час. - Створити консольну програму, яка генерує масив з
рядків-записів «ім’я;місто;вік» (фіксоване зерно) і за допомогою PLINQ (AsParallel,Where,GroupBy) обчислює кількість людей, старших за вік, введений користувачем, для кожного міста. Результат виводиться, відсортований за назвою міста, разом із часом PLINQ і LINQ та перевіркою збігу результатів. - Створити консольну програму, яка за допомогою PLINQ
Aggregateз функціями seed, update, combine і result обчислює для масиву з випадкових цілих чисел (розмір вводить користувач) одночасно мінімум, максимум, суму й кількість парних чисел. Програма перевіряє результат послідовним обчисленням і виводить його та час. - Створити консольну програму, яка знаходить у масиві з 50 000 000 випадкових цілих чисел індекс першого елемента, рівного числу, введеному користувачем, за допомогою
Parallel.ForзParallelLoopState.Break. Програма виводитьIsCompleted,LowestBreakIteration, результат послідовного пошуку та час обох пошуків або повідомлення, що число відсутнє. - Створити консольну програму, яка сортує масив з
випадкових цілих чисел (розмір і поріг вводить користувач) паралельним сортуванням злиттям: дві половини сортуються черезParallel.Invoke, фрагменти, менші за поріг, сортуютьсяArray.Sort. Програма перевіряє впорядкованість результату та виводить час паралельного сортування, послідовного сортування злиттям і прискорення. - Створити консольну програму, яка оцінює число π методом Монте-Карло для кількості випробувань, введеної користувачем, розбиваючи випробування на 64 блоки з власними генераторами
new Random(seed + номер блоку)уParallel.For. Програма виводить оцінку, похибку й таблицю часу, прискорення та ефективності для 1, 2, 4 і 8 потоків. - Створити консольну програму, яка знаходить максимум масиву з
випадкових чисел ( від 10 до 26 вводить користувач) паралельною редукцією: на кожному рівні дерева попарні максимуми обчислюються черезParallel.Forу новий масив удвічі меншої довжини. Програма виводить максимум, кількість рівнів і перевіряє результат зEnumerable.Max. - Створити консольну програму, яка обробляє 100 імітованих «файлів» (кожен – затримка
Task.Delayвід 100 до 500 мс і підрахунок суми випадкових чисел) за допомогоюParallel.ForEachAsyncз обмеженням кількості одночасних операцій, введеним користувачем, і маркером скасування, що спрацьовує через задану кількість секунд. Програма виводить кількість оброблених файлів, загальну суму та час або повідомлення про скасування. - Створити консольну програму, яка обчислює множину Мандельброта на зображенні, розміри якого вводить користувач, за допомогою
Parallel.Forза рядками зParallelOptions.MaxDegreeOfParallelismдля 1, 2, 4, 8 і 16 потоків. Для кожної кількості потоків програма виводить медіану трьох запусків, прискорення й ефективність і перевіряє, що загальна кількість ітерацій збігається з послідовною версією.
Тема 7. Векторизація SIMD
- Створити консольну програму, яка виводить значення
Vector.IsHardwareAccelerated,Vector<float>.Count,IsHardwareAcceleratedдляVector128,Vector256,Vector512таIsSupportedдляAvx2,Fma,Avx512F,AdvSimdу вирівняній таблиці, а також найширший прискорений вектор цього ПК. - Створити консольну програму, яка запитує довжину масиву (від 0 до 10 000 000), заповнює масив
intвипадковими числами й обчислює суму скалярно та за допомогоюVector<int>з обробкою хвоста, перевіряє збіг сум і виводить час обох способів. - Створити консольну програму, яка множить масив
floatна число, введене користувачем, і додає до іншого масиву (операціяaxpy) скалярно таVector256<float>з обробкою хвоста, перевіряє результат для довжин 0, 1, 7, 8, 9 і 1 000 003 і виводить час. - Створити консольну програму, яка замінює в масиві
shortз 10 000 000 відліків усі значення, більші за введений поріг, на поріг, скалярно та векторно (Vector256.GreaterThanіConditionalSelect), і виводить кількість змінених значень та час обох способів. - Створити консольну програму, яка знаходить у текстовому файлі, шлях до якого вводить користувач, позиції всіх входжень введеного символу ASCII за допомогою
Vector128.EqualsіExtractMostSignificantBits, виводить кількість і перші 10 позицій та перевіряє результат скалярним пошуком. - Створити консольну програму, яка генерує 100 000 векторів розмірністю 128, знаходить для введеного номера вектора 5 найбільш схожих за косинусною подібністю (
TensorPrimitives.CosineSimilarity) і виводить таблицю «номер – подібність» та час. - Створити консольну програму, яка запитує розмір матриць
і розмір плитки, множить матриціdoubleпорядком ikj і блочно, перевіряє збіг результатів і виводить час та GFLOPS обох способів. - Створити консольну програму, яка розв’язує СЛАР з діагональною перевагою, розмір якої вводить користувач, методом Якобі з
Parallel.Forза рядками до точності і виводить кількість ітерацій, максимальну похибку розв’язку та час послідовної й паралельної версій. - Створити консольну програму, яка розв’язує СЛАР розміром
(вводить користувач) методом Гаусса з вибором головного елемента, виконуючи виключення рядків черезParallel.ForіTensorPrimitives.MultiplyAdd, та виводить нев’язку і час. - Створити консольну програму, яка нормалізує 1 000 000 векторів
Vector3методомVector3.Normalizeі векторно для окремих масивів координат (Vector256<float>,Vector256.Sqrt), перевіряє максимальну різницю та виводить час і прискорення.
Тема 8. Паралельні алгоритми
- Створити консольну програму, яка запитує межі інтегрування й точність і обчислює
паралельною складеною формулою Сімпсона, подвоюючи кількість відрізків, доки оцінка похибки за правилом Рунге не стане меншою за задану точність; виводить значення, кількість відрізків, оцінку похибки і час. - Створити консольну програму, яка обчислює
адаптивним методом Сімпсона з рекурсивними задачамиParallel.Invokeдо введеної користувачем глибини, виводить значення, похибку відносно , кількість задач і час порівняно з послідовною версією. - Створити консольну програму, яка запитує довжину векторів і кількість потоків і обчислює скалярний добуток блочним, циклічним і блочно-циклічним (блоки по 1024) розподілами, виводячи результати з 17 цифрами та час кожного розподілу.
- Створити консольну програму, яка запитує розмір матриці
і кількість потоків, множить випадкову матрицю на вектор горизонтальними смугами, перевіряє результат послідовним множенням і виводить час, прискорення та ефективність. - Створити консольну програму, яка запитує розмір матриць
(кратний 4) і множить їх шаховою схемою (16 задач, кожна обчислює свій блок ), перевіряє результат послідовним множенням і виводить час обох способів і прискорення. - Створити консольну програму, яка знаходить усі корені функції
на відрізку, введеному користувачем: паралельно відокремлює корені на сітці із заданою кількістю відрізків і уточнює їх бісекцією до ; виводить корені та час. - Створити консольну програму, яка для введеної кількості початкових швидкостей розв’язує рівняння маятника з опором методом Рунге–Кутти 4-го порядку до зупинки маятника паралельно з динамічним розподілом задач і виводить кількість обертів для кожної десятої швидкості та час.
- Створити консольну програму, яка множить матриці
(вводить користувач) смугами на 1, 2, 4 і 8 потоках, вимірює час і виводить таблицю «потоки – прогноз – виміряне – ефективність». - Створити консольну програму, яка оцінює об’єм кулі радіуса 1 методом Монте-Карло за введеною кількістю точок з окремим генератором на кожен з 64 блоків і виводить оцінку, довірчий інтервал і перевірку, що два запуски дають однаковий результат.
- Створити консольну програму, яка розв’язує тридіагональну систему
розміру (вводить користувач, з відомого розв’язку) методом спряжених градієнтів з паралельними детермінованими скалярними добутками і виводить кількість ітерацій, нев’язку та час послідовної й паралельної версій.
Тема 9. Багатопотоковість у C++
- Створити проєкт CMake (ціль
Threads::Threads, стандарт C++23, пресети debug і release з генератором Ninja) з консольною програмою мовою C++, яка запитує розмір масиву й кількість потоків, обчислює суму квадратів елементів у потокахstd::jthreadі виводить суму, час і прискорення порівняно з послідовним обчисленням. - Створити консольну програму мовою C++, яка запитує
і кількість потоків , підраховує кількість простих чисел до , розбиваючи діапазон на частин для потоківstd::jthread, перевіряє результат послідовним підрахунком і виводить таблицю часу, прискорення й ефективності для від 1 до введеного значення. - Створити консольну програму мовою C++, у якій 8 потоків виконують введену кількість переказів між 5 рахунками з
std::scoped_lock, а окремий лічильник успішних переказів реалізовано черезstd::atomic. Програма перевіряє незмінність загальної суми й виводить баланси та кількість успішних і відхилених переказів. - Створити консольну програму мовою C++ з потокобезпечною чергою на
std::mutexіstd::condition_variable, у якій 2 виробники генерують введену кількість завдань, а 3 споживачі їх обробляють (обчислюють факторіал за модулем ). Програма коректно завершує споживачів і виводить кількість оброблених завдань кожним споживачем і суму результатів. - Створити консольну програму мовою C++, яка для введеного каталогу запускає для кожного підкаталогу задачу
std::async(std::launch::async, …), що підраховує кількість і розмір файлів.cppі.hза допомогоюstd::filesystem, і виводить таблицю підкаталогів, загальні підсумки та повідомлення про помилки, отримані черезfuture. - Створити консольну програму мовою C++ з пулом потоків на
std::jthread,std::condition_variableіstd::packaged_task, який приймає задачі обчислення числа Фібоначчі за модулем для введених користувачем номерів і повертає результати черезstd::future; програма виводить результати в порядку введення та кількість потоків пулу. - Створити консольну програму мовою C++, яка генерує введену кількість випадкових дійсних чисел, сортує їх
std::sortз політикамиseqіparта обчислює середнє квадратичнеstd::transform_reduceз політикамиseq,parіpar_unseq. Програма виводить таблицю часу, прискорення й перевірку однаковості результатів. - Створити консольну програму мовою C++, яка запускає 4 робочі потоки
std::jthread, що до запиту зупинки черезstd::stop_tokenобчислюють суму випадкових чисел, а головний потік зупиняє їх через кількість секунд, введену користувачем. Програма виводить кількість оброблених чисел і суму кожного потоку. - Створити консольну програму мовою C++, у якій 10 потоків-відвідувачів користуються читальним залом на 3 місця, обмеженим
std::counting_semaphore, а синхронний старт усіх відвідувачів забезпечуєstd::latch. Програма виводить журнал подій і перевіряє, що в залі ніколи не було більше 3 відвідувачів. - Створити консольну програму мовою C++, яка обчислює інтеграл функції
на введеному відрізку методом трапецій у потоках, вимірює час годинникомstd::chrono::steady_clockяк медіану трьох запусків і виводить таблицю , , , та значення інтеграла.
Тема 10. OpenMP
- Створити консольну програму мовою C++ з OpenMP, яка запитує кількість потоків (від 1 до 64) і в паралельній області виводить для кожного потоку його номер, кількість потоків команди та приватну змінну, ініціалізовану через
firstprivateзначенням, введеним користувачем, збільшеним на номер потоку; після області програма виводить значення цієї змінної й пояснює, чому воно не змінилося. - Створити консольну програму мовою C++ з OpenMP, яка запитує кількість відрізків
і обчислює число як інтеграл на директивоюparallel for reduction(+:sum)для 1, 2, 4, 8 і 16 потоків, виводячи таблицю значення, похибки, часу (omp_get_wtime), прискорення й ефективності. - Створити консольну програму мовою C++ з OpenMP, яка запитує верхню межу
і підраховує прості числа до зschedule(static),schedule(dynamic, 100)іschedule(guided), перевіряє однаковість кількості простих чисел і виводить таблицю часу для кожного виду розподілу. - Створити консольну програму мовою C++ з OpenMP, яка генерує масив із
випадкових цілих чисел ( вводить користувач, фіксоване зерно) і паралельно знаходить суму, мінімум, максимум і кількість парних чисел клаузамиreduction, перевіряє результати послідовним обходом і виводить їх. - Створити консольну програму мовою C++ з OpenMP, яка генерує
оцінок студентів від 0 до 100 і будує гістограму з 10 інтервалів трьома способами (critical,atomic,reduction(+:hist[0:10])), перевіряє однаковість гістограм і виводить гістограму та час кожного способу. - Створити консольну програму мовою C++ з OpenMP, яка запитує
(від 20 до 45) і обчислює -те число Фібоначчі рекурсивно задачамиtaskіtaskwaitз порогом, нижче якого обчислення послідовне; програма виводить результат і час для порогів 10, 20 і 30. - Створити консольну програму мовою C++ з OpenMP, яка сортує масив із
випадкових чисел ( вводить користувач) рекурсивним сортуванням злиттям із задачами OpenMP і порогом 10 000 елементів, перевіряє впорядкованість і виводить час паралельного сортування таstd::sort. - Створити консольну програму мовою C++ з OpenMP, яка обчислює скалярний добуток двох векторів із
дійсних чисел ( вводить користувач) чотирма способами: звичайним циклом,omp simd reduction,parallel for reductionіparallel for simd reduction, перевіряє відносну розбіжність результатів (не більше ) і виводить таблицю часу та прискорення. - Створити консольну програму мовою C++ з OpenMP, яка виводить значення
omp_get_proc_bind, кількість місцьomp_get_num_placesі процесори кожного місця, а в паралельній області – номер потоку та номер його місцяomp_get_place_num. Запустити програму зі зміннимиOMP_PLACES=coresіOMP_PROC_BIND=closeтаspreadі пояснити різницю виведення. - Створити консольну програму мовою C++ з OpenMP, яка запитує розмір квадратних матриць
і множить дві випадкові матриці директивоюparallel forза рядками для 1, 2, 4, 8 і 16 потоків, перевіряє збіг результату з послідовним множенням і виводить таблицю часу, прискорення та ефективності .
Тема 11. Обчислення на GPU
- Створити консольну програму мовою CUDA C++, яка запитує довжину двох векторів, заповнює їх випадковими числами, обчислює їх поелементний добуток ядром з глобальним індексом і перевіркою меж, перевіряє результат на CPU і виводить найбільшу похибку.
- Створити консольну програму мовою CUDA C++, яка виділяє пам’ять пристрою для масиву з
чисел ( вводить користувач), копіює дані на GPU, множить кожен елемент на 2 ядром, копіює результат назад, звільняє пам’ять і перевіряє всі виклики CUDA. - Створити консольну програму мовою CUDA C++, яка інвертує згенероване зображення 1920×1080 у відтінках сірого ядром на 2D-сітці блоків 16×16, записує результат у PGM і виводить розміри сітки.
- Створити консольну програму мовою CUDA C++, яка транспонує матрицю
( вводить користувач) наївним ядром і ядром з тайлом 32×32 у спільній пам’яті, перевіряє результати та виводить час обох ядер, виміряний подіями CUDA. - Створити консольну програму мовою CUDA C++, яка обчислює суму масиву з
цілих чисел редукцією з послідовною адресацією у спільній пам’яті таatomicAdd, порівнює результат і час з OpenMP. - Створити консольну програму мовою CUDA C++, яка будує гістограму з 10 інтервалів для
випадкових оцінок від 0 до 100 локальними гістограмами у спільній пам’яті та виводить гістограму й час. - Створити консольну програму мовою CUDA C++, яка для масиву з
чисел вимірює подіями CUDA окремо час копіювання на GPU, роботи ядра (квадрат кожного елемента) і копіювання назад та виводить прискорення відносно OpenMP з урахуванням копіювань і без нього. - Створити консольну програму мовою C# з ILGPU, яка виводить перелік доступних пристроїв, обирає GPU (або CPU-акселератор) і обчислює SAXPY для
чисел ядром зIndex1DіMemoryBuffer1D, перевіряючи результат. - Створити консольну програму мовою C# з ILGPU, яка розмиває згенероване зображення середнім 3×3 ядром з
Index2Dі порівнює час зParallel.Forз урахуванням копіювань. - Створити консольну програму мовою CUDA C++, яка обробляє масив частинами у чотирьох потоках CUDA із закріпленою пам’яттю (копіювання, ядро, копіювання) і порівнює час з обробкою без потоків.
Тема 12. Передавання повідомлень MPI
- Створити консольну програму мовою C++ з MPI, у якій кожен процес виводить свій ранг, кількість процесів і ім’я вузла, а ранг 0 додатково збирає ранги всіх процесів операцією
MPI_Gatherі виводить їх у порядку зростання. - Створити консольну програму мовою C++ з MPI, яка обчислює суму чисел від 1 до
( вводить користувач на ранзі 0): ранг 0 розсилає операцієюMPI_Bcast, кожен ранг підсумовує свою частину,MPI_Reduceзбирає результат, який порівнюється з формулою. - Створити консольну програму мовою C++ з MPI, у якій ранги утворюють кільце й передають по ньому маркер (число), кожен ранг додає до нього свій ранг; обмін без взаємоблокувань для будь-якої кількості процесів, ранг 0 виводить підсумок.
- Створити консольну програму мовою C++ з MPI, у якій кожен ранг обмінюється масивом з
чисел з обома сусідами в кільці неблокуючими операціямиMPI_IsendіMPI_IrecvзMPI_Waitallта виводить суму отриманих значень. - Створити консольну програму мовою C++ з MPI, яка розподіляє масив з
чисел ( вводить користувач, може не ділитися на кількість процесів) операцієюMPI_Scatterv, знаходить мінімум, максимум і середнє та виводить їх на ранзі 0. - Створити консольну програму мовою C++ з MPI, яка множить матрицю
на вектор: рядки матриці розподіляютьсяMPI_Scatter, вектор –MPI_Bcast, результат збираєтьсяMPI_Gatherі перевіряється послідовним множенням. - Створити консольну програму мовою C++ з MPI за схемою «майстер–робітник», у якій ранг 0 роздає робітникам по одному 1000 чисел для перевірки на простоту, збирає відповіді й виводить кількість простих і кількість чисел, перевірених кожним робітником.
- Створити консольну програму мовою C++ з MPI, яка створює двовимірну періодичну декартову топологію процесів, знаходить сусідів кожного процесу
MPI_Cart_shiftі обмінюється з ними рангами, а кожен процес виводить свої координати й ранги сусідів. - Створити консольну програму мовою C++ з MPI і OpenMP, яка ініціалізує MPI функцією
MPI_Init_threadзMPI_THREAD_FUNNELED, обчислює інтегруванням: кроки діляться між рангами, у межах рангу – потоками зreduction, і виводить кількість рангів, потоків і результат. - Створити консольну програму мовою C++ з MPI, яка вимірює
MPI_Wtimeчас обчислення суми чисел для поточної кількості процесів (час найповільнішого рангу, медіана 5 запусків міжMPI_Barrier) і виводить час, прискорення відносно послідовного обчислення на ранзі 0 та ефективність.
Тема 13. Кластер і планувальник Slurm
- Створити скрипт
sbatchдля послідовної програми./modelз аргументамиinput.dat 1000: 1 задача, 2 ГБ пам’яті, ліміт 30 хв, розділdebug, файл виводу з назвою завдання й номером; після виконання програми скрипт виводить код її завершення й час роботи в секундах (зміннаSECONDS). - Створити скрипт
sbatchдля багатопотокової програми OpenMP на одному вузлі з 8 CPU і 4 ГБ пам’яті, у якому кількість потоків береться зі змінної Slurm, прив’язка потоків задаєтьсяOMP_PLACES=coresіOMP_PROC_BIND=close, а перед запуском виводяться вузол, кількість виділених CPU і значення змінних OpenMP. - Створити MPI-програму мовою C++, у якій кожен ранг виводить свій номер, кількість рангів і ім’я вузла, а ранг 0 збирає імена вузлів (
MPI_Gather) і виводить, скільки рангів працює на кожному вузлі; та скриптsbatchдля 3 вузлів по 4 ранги із запуском черезsrun --mpi=pmix. - Створити скрипт
sbatchдля гібридної програми MPI + OpenMP на 2 вузлах з 2 рангами на вузлі та 4 потоками на ранг: директиви розкладки, зміннаOMP_NUM_THREADS, запуск черезsrun; перед запуском скрипт перевіряє, що добуток кількості рангів на кількість потоків дорівнює кількості виділених CPU, і завершується з кодом 1, якщо ні. - Створити скрипт
sbatchз масивом із 50 елементів (не більше 10 одночасно), у якому елемент обробляє -й рядок файлуparams.txt(параметри програми./sim), записує результат уresults/<i>.txt, та скрипт, що після завершення масиву (залежність) об’єднує результати й виводить номери елементів без результату. - Створити скрипт bash, який надсилає ланцюжок із трьох завдань
a.sbatch→b.sbatch→c.sbatchз умовамиafterokі завданняcleanup.sbatchз умовоюafteranyна останнє завдання ланцюжка, виводить номери завдань, а після завершення – таблицю станів і кодів завершення всіх чотирьох завдань заsacct. - Створити скрипт bash, який виводить: розділи кластера з кількістю вільних і зайнятих вузлів (
sinfo), свої завдання з причинами очікування (squeueз власним форматом), очікуваний час старту завдань, що чекають, і пропонує скасувати (scancel) завдання, які чекають понад задану користувачем кількість годин. - Створити скрипт bash, який за виводом
sacct -X --parsable2за період, що вводить користувач, виводить таблицю завдань «номер – назва – стан – код завершення – тривалість – CPU·год» і підсумок: кількість завдань за станами та загальні CPU·год. - Записати фрагмент
slurm.confдля кластера з керувальним вузломheadі вузламиnode[01-04](8 CPU: 1 сокет, 4 ядра, 2 потоки, 16 ГБ пам’яті з резервом для ОС) з розподілом ядер і пам’яті, прив’язкою задач через cgroup, розділамиshort(усі вузли, 1 год, за замовчуванням) іlong(вузли 3–4, 3 доби); та скрипт bash, який перевіряє синтаксис фрагмента (обов’язкові параметри, формат часу, існування вузлів розділів). - Створити діагностичний скрипт bash для обчислювального вузла, який перевіряє й виводить у вигляді таблиці «параметр – значення – рекомендовано»: регулятор частоти, режим THP,
vm.swappiness,kernel.numa_balancing, лімітиmemlockіnofile, MTU мережевого інтерфейсу, стан службmunge,slurmd,chronyі стан вузла в Slurm (sinfo -n).
Тема 14. Сокети, RPC і gRPC
- Створити асинхронний TCP-сервер, який одночасно обслуговує кількох клієнтів і на кожен рядок відповідає цим рядком у верхньому регістрі, та клієнт, що надсилає рядки з клавіатури; сервер виводить підключення й відключення клієнтів.
- Створити TCP-клієнт і сервер калькулятора з кадруванням «довжина (4 байти) + JSON»: клієнт надсилає операцію та два числа, сервер повертає результат або повідомлення про помилку (ділення на нуль, невідома операція).
- Створити UDP-сервер, який на запит «TIME» повертає поточний час, та клієнт, що надсилає 10 запитів з таймаутом 1 с, повторює загублені й виводить затримку кожного запиту та кількість втрат.
- Створити TCP-клієнт, який підключається до сервера з повторними спробами (3 спроби, експоненційна затримка, таймаут з’єднання 2 с) і виводить причину кожної невдачі (
SocketError) та підсумкове повідомлення. - Описати в
.protoсервіс студентів з методамиGetStudent(id)іAddStudent(student), реалізувати gRPC-сервер на ASP.NET Core і клієнт; неіснуючий студент повертає кодNotFound, який клієнт виводить. - Створити gRPC-сервіс із серверним потоком, що надсилає N простих чисел з паузою 200 мс, та клієнт, який виводить їх; клієнт задає дедлайн 1 с і виводить отримані числа та код статусу
DeadlineExceeded. - Створити gRPC-сервіс із клієнтським потоком, що приймає числа й повертає їхню кількість, суму та середнє, і клієнт, який надсилає числа з текстового файлу.
- Створити gRPC-сервіс луни з двонаправленим потоком, який на кожне повідомлення відповідає двома повідомленнями, та клієнт, що одночасно надсилає й читає повідомлення, виводячи порядок отримання.
- Створити gRPC-сервіс з перехоплювачем, який записує в консоль назву методу, тривалість і код статусу кожного виклику, та клієнт, що передає метадані
client-nameі виконує успішний і помилковий виклики. - Створити сервіс CoreWCF з контрактом
[ServiceContract](операції «додати» та «перелік» нотаток) і кінцевою точкоюBasicHttpBinding, та консольний клієнт наSystem.ServiceModel.Http, що викликає обидві операції й обробляєFaultException.
Тема 15. Брокер RabbitMQ
- Створити видавця, який публікує в стійку чергу RabbitMQ N повідомлень (N вводиться з клавіатури), і споживача з ручними підтвердженнями, що виводить кожне повідомлення та їх загальну кількість.
- Створити чергу завдань із двома робітниками: завдання містить тривалість обробки в мілісекундах, робітники мають prefetch 1 і ручні підтвердження; вивести, які завдання виконав кожен робітник, і загальний час.
- Створити видавця, який публікує повідомлення журналу в обмінник direct з ключами
info,warning,error, і два споживачі: перший отримує лишеerror, другий – усі рівні; кожен виводить отримані повідомлення. - Створити видавця подій в обмінник fanout і три споживачі зі стійкими чергами; показати, що споживач, запущений пізніше, отримує події, опубліковані до його запуску.
- Створити видавця подій з ключами
<місто>.<тип>в обмінник topic і споживача, який приймає шаблони прив’язки аргументами командного рядка та виводить отримані події. - Створити видавця з підтвердженнями видавця та
mandatory: true, який публікує повідомлення в чергу, ім’я якої вводиться з клавіатури, і виводить «підтверджено» або причину відмови (PublishException, повернення). - Створити чергу
tasksз dead letter exchange: споживач відхиляє повідомлення з непарними номерами (requeue: false), а другий споживач черги відхилених виводить їх разом із причиною з заголовкаx-death. - Створити RPC через черги: сервер обчислює факторіал числа, клієнт надсилає три запити одночасно з різними
CorrelationId, чекає відповідей не довше 2 с і виводить результати або повідомлення про таймаут. - Створити ідемпотентного споживача платежів: видавець публікує платежі з
MessageId, серед яких є дублікати; споживач зараховує кожен платіж один раз і виводить баланс і кількість пропущених дублікатів. - Створити координатора, який ділить обчислення суми квадратів чисел від 1 до N на K частин і публікує їх у чергу, та робітника, що обчислює частини й повертає результат; координатор виводить суму, перевіряє її формулою і виводить час.
Тема 16. Актори та Microsoft Orleans
- Створити застосунок Orleans (силос і клієнт в одному процесі) із зерном лічильника (ключ – рядок) з методами
IncrementіGet; клієнт виконує 1000 одночасних викликівIncrementдля двох лічильників і виводить значення та час. - Створити силос і окремий консольний клієнт Orleans із зерном нотаток користувача (ключ – ім’я), методами «додати» та «перелік»; клієнт виконує команди з клавіатури.
- Створити застосунок Orleans із зерном профілю користувача, стан якого зберігається через
IPersistentStateу провайдері Redis або пам’яті; після перезапуску програми профіль читається знову й виводиться. - Створити застосунок Orleans із зерном таймера вікторини, яке після старту щосекунди таймером (
RegisterGrainTimer) виводить час, що залишився, і через 10 с завершує раунд. - Створити застосунок Orleans із зерном підписки, яке нагадуванням (провайдер у пам’яті, мінімальний період зменшено до 5 с) тричі виводить повідомлення про оплату й скасовує нагадування.
- Створити застосунок Orleans із двома зернами, що викликають одне одного по колу, і продемонструвати
TimeoutExceptionта його усунення за допомогою[Reentrant]абоRequestContext.AllowCallChainReentrancy; вивести час виконання. - Створити застосунок Orleans із
[StatelessWorker]-зерном перевірки e-mail і зерном статистики; клієнт перевіряє 1000 адрес з файлу, а програма виводить кількість коректних і некоректних адрес. - Створити консольну програму, що викликає ненадійну операцію (виняток з імовірністю 50 %) з повторами: 4 спроби, експоненційна затримка 100, 200, 400 мс з джитером; вивести кожну спробу та підсумок.
- Створити консольну програму, що моделює N = 5 реплік і для введених W та R виконує 10 000 операцій запису й читання, виводячи частку застарілих читань і перевірку умови R + W > N.
- Створити консольну програму з актором на
Channel<T>, який веде облік товарів (надходження, продаж, залишок); 8 задач одночасно надсилають повідомлення, а програма виводить правильний залишок.
Тема 17. Docker, Kubernetes, Aspire
- Створити багатоетапний
Dockerfileдля вебсервісу ASP.NET Core на .NET 10 з фінальним образомaspnet:10.0, запуском від користувачаappі файлом.dockerignore; зібрати образ, запустити контейнер з публікацією порту 8080 і перевірити сервіс. - Створити
compose.yamlіз сервісом API, брокером RabbitMQ зhealthcheckі робітником; API й робітник запускаються після готовності брокера, рядок підключення передається змінною середовища, робітників масштабують командоюdocker compose up --scale. - Створити стенд Docker Compose із вебсервісом і Redis, дані Redis зберігаються в іменованому томі; показати, що дані переживають
docker compose downі повторнийup. - Створити маніфести Kubernetes для вебсервісу: Deployment на 3 репліки, Service типу NodePort, ConfigMap з параметрами, переданими через
envFrom; розгорнути їх командоюkubectl applyі показати розподіл запитів між подами. - Створити Deployment вебсервісу ASP.NET Core з
readinessProbe,livenessProbe,requestsіlimits; продемонструвати виключення неготового пода зі служби та перезапуск контейнера після невдалої проби життєздатності. - Розгорнути Deployment вебсервісу ASP.NET Core і виконати його поступове оновлення на нову версію образу з параметрами
maxSurge: 1іmaxUnavailable: 0, переглянути історію ревізій і виконати відкат командоюkubectl rollout undo. - Створити індексоване завдання Kubernetes (
completions: 6,parallelism: 3), кожен под якого обчислює суму квадратів свого діапазону чисел заJOB_COMPLETION_INDEX; зібрати результати з журналів і вивести загальну суму. - Створити HorizontalPodAutoscaler для обчислювального вебсервісу (від 1 до 5 реплік, ціль 50 % процесора) і показати зміну кількості реплік під навантаженням командою
kubectl get hpa -w. - Створити рішення Aspire з AppHost, ServiceDefaults, вебсервісом і Redis: рядок підключення передається через
WithReference, сервіс запускається після готовності Redis (WaitFor), робітник має дві репліки (WithReplicas); показати ресурси в дашборді. - Створити вебсервіс у рішенні Aspire з власною метрикою OpenTelemetry (лічильник запитів із міткою результату) і власним спаном
ActivitySourceдля обчислення; показати метрику й трасування в дашборді Aspire.
Тема 18. Архітектура мікросервісів
- Створити рішення Aspire з двома вебсервісами (каталог товарів і замовлення), кожен з власною базою PostgreSQL, і шлюзом YARP, який маршрутизує
/api/catalog/**і/api/orders/**через виявлення сервісів; замовлення перевіряє товар викликом каталогу, а неіснуючий товар повертає код 400. - Створити сервіс, який публікує подію «замовлення створено» в RabbitMQ, і споживача, що обробляє її ідемпотентно: оброблені ідентифікатори повідомлень зберігаються в таблиці Inbox, а повторна доставка тієї самої події не змінює результат; показати це повторною публікацією.
- Створити оркестровану сагу оформлення замовлення з кроками «резерв товару → оплата → підтвердження»: при відмові оплати виконується компенсація (зняття резерву), стан саги зберігається в базі даних, а запит стану повертає журнал кроків таблицею.
- Реалізувати Transactional Outbox: сервіс записує замовлення й повідомлення в таблицю Outbox в одній транзакції EF Core, а фоновий ретранслятор публікує повідомлення в RabbitMQ; показати, що при зупиненому брокері повідомлення не губляться.
- Створити два вебсервіси, де HTTP-клієнт першого викликає другий із політикою стійкості
Microsoft.Extensions.Http.Resilience(тайм-аут, три повтори, запобіжник); продемонструвати роботу запобіжника, зупинивши викликаний сервіс, і вивести зміни його стану в журнал. - Створити рішення Aspire зі шлюзом YARP, двома HTTP-сервісами й споживачем RabbitMQ, налаштувати трасування OpenTelemetry для запиту, що проходить через них, додати власний спан
ActivitySourceз атрибутами та показати в дашборді Aspire одне трасування з усіма спанами. - Створити вебсервіс із двома версіями API (
/v1/...і/v2/...), де друга версія розширює формат відповіді, а перша позначена застарілою заголовком відповіді; показати, що старий і новий клієнти працюють одночасно. - Створити рішення Aspire з вебсервісами, що використовують PostgreSQL і RabbitMQ, і перевірками працездатності
/healthі/alive, де готовність залежить від доступності бази даних і брокера; показати зміну стану ресурсу в дашборді після зупинки бази даних. - Створити шлюз YARP перед вебсервісом з обмеженням частоти запитів (5 запитів за 10 с на клієнта), кодом 429 і заголовком
Retry-After; консольний клієнт надсилає 20 запитів і виводить таблицю «номер – код – час». - Створити інтеграційний тест
Aspire.Hosting.Testing, який запускає AppHost з двома сервісами й шлюзом, чекає готовності ресурсів, виконує запити через шлюз і перевіряє коди відповідей та вміст для успішного й помилкового сценаріїв.