Контрольні питання:
Поясніть основні підходи до розпаралелення задачі сортування масивів?
Чим відрізняється сортування масивів для одно- та багатопроцесорних систем.
Поясніть принцип сортування масиву з 5-ти чисел за допомогою двох процесорів?
Чому при збільшенні кількості процесорів до 3-х кількість кроків (час виконання програми) для сортування масиву з 5-ти чисел не змінеться?
Що таке мютекс: призначення, особливості та галузі використання?
Які операції існують для роботи з мютексами?
Чим мютекс відрізняється від бінарного семафору?
Лабораторна робота №5
Тема: «Розподілені обчислення»
Мета роботи: ознайомитися з принципами організації розподілених обчислень та механізмом сокетів зокрема на прикладі вирішення задачі перевірки ізоморфності графів
Задача
Задано дві матриці суміжності двох графів. Перевірити ізоморфність цих двох графів. Написати програму-клієнт, яка відправляє на сервер дані матриці, і програму-сервер, яка проводить обробку матриці і відправляє клієнту відповідь, ізоморфні графи чи ні.
Сокети
Найрозповсюдженим методом обміну повідомленнями є використання сокетів (sockets). Ця технологія насамперед призначена для організації мережного обміну даними, але може бути використана й для взаємодії між процесами на одному комп’ютері (власне, мережну взаємодію можна розуміти як узагальнення IPC).
Сокет — це абстрактна кінцева точка з’єднання, через яку процес може відсилати або отримувати повідомлення. Обмін даними між двома процесами здійснюють через пару сокетів, по одному на кожен процес. Абстрактність сокету полягає в тому, що він приховує особливості реалізації передачі повідомлень — після того як сокет створений, робота з ним не залежить від технології передачі даних, тому один і той самий код можна без великих змін використовувати для роботи із різними протоколами зв’язку.
Особливості протоколу передачі даних і формування адреси сокету визначає комунікаційний домен — його потрібно зазначити під час створення кожного сокету. Прикладами доменів можуть бути домен Інтернету (який задає протокол зв’язку на базі TCP/IP) і локальний домен або домен UNIX, що реалізує зв’язок із використанням імені файлу (подібно до поіменованого каналу). Сокет можна використовувати у поєднанні тільки з одним комунікаційним доменом. Адреса сокету залежить від домену (наприклад, для сокетів домену UNIX такою адресою буде ім’я файлу).
Способи передачі даних через сокет визначаються його типом. У конкретному домені можуть підтримуватися або не підтримуватися різні типи сокетів. Наприклад, і для домену Інтернету, і для домену UNIX підтримуються сокети таких типів:
потокові (stream sockets) — задають надійний двобічний обмін даними суцільним потоком без виділення меж (операція читання даних повертає стільки даних, скільки запитано або скільки було на цей момент передано);
дейтаграмні (datagram sockets) — задають ненадійний двобічний обмін повідомлення із виділенням меж (операція читання даних повертає розмір того повідомлення, яке було відіслано).
Під час обміну даними із використанням сокетів зазвичай застосовується технологія клієнт-сервер, коли один процес (сервер) очікує з’єднання, а інший (клієнт) з’єднують із ним.
Перед тим як почати працювати з сокетами, будь-який процес (і клієнт, і сервер) має створити сокет за допомогою системного виклику socket(). Параметрами цього виклику є комунікаційний домен і тип сокету. Цей виклик повертає дескриптор сокету — унікальне значення, за яким можна буде звертатися до цього сокету.
Подальші дії відрізняються для сервера і клієнта. Спочатку розглянемо послідовність кроків, яку потрібно виконати для сервера.
Сокет пов’язують з адресою за допомогою системного виклику bind(). Для сокетів домену UNIX як адресу задають ім’я файлу, для сокетів домену Інтернету — необхідні характеристики мережного з’єднання. Далі клієнт для встановлення з’єднання й обміну повідомленнями має вказати саме цю адресу.
Сервер дає змогу клієнтам встановлювати з’єднання, виконавши системний виклик listen() для дескриптора сокету, створеного раніше.
Після виходу із системного виклику listen() сервер готовий приймати від клієнтів запити на з’єднання. Ці запити вишиковуються в чергу. Для отримання запиту із цієї черги і створення з’єднання використовують системний виклик accept(). Внаслідок його виконання у використання повертають новий сокет для обміну даними із клієнтом. Старий сокет можна використовувати далі для приймання нових запитів для з’єднання. Якщо під час виклику accept() запити на з’єднання в черзі відсутні, сервер переходить у стан очікування.
Для клієнта послідовність дій після створення сокету зовсім інша. Замість трьох кроків досить виконати один — встановлення з’єднання із використанням системного виклику connect(). Параметрами цього виклику задають дескриптор створеного раніше сокету, а також адресу, подібну до вказаної на сервері для виклику bind().
Після встановлення з’єднання (і на клієнті, і на сервері) з’явиться можливість передавати і приймати дані з використанням цього з’єднання. Для передачі даних застосовують системний виклик send(), а для приймання — recv().
Зазначену послідовність кроків використовують для встановлення надійного з’єднання. Якщо все, що нам потрібно — це відіслати і прийняти конкретне повідомлення фіксованої довжини, то з’єднання можна й не створювати зовсім. Для цього як відправник, так і одержувач повідомлення мають попередньо зв’язати сокети з адресами через виклик bind(). Потім можна скористатися викликами прямої передачі даних: sendto() — для відправника і recvfrom() — для одержувача. Параметрами цих викликів є адреси одержувача і відправника, а також адреси буферів для даних.
Листинг програми клієнта
#include <iostream.h>
#include <windows.h>
#include <conio.h>
#pragma comment (lib, "ws2_32.lib")
#pragma comment (lib, "mswsock.lib")
void main(void) {SetConsoleOutputCP(1251); //Використання кодування 1251
char PCName[30], ServerName[30], IP[16] = { 0 };
char a[8],Message[42];
int Messag0e[200], i,j;
WSAData WSADat; // Властивості WinSock (результат функції WSAStartup)
sockaddr_in sin; // Властивості (адреса) сокету, що створюється
SOCKET Sock; // Клієнтський сокет
// Введення IP-адреси сервера
cout << "Enter server's IP: ";
cin.getline(IP, 16);
WSAStartup(0x0202, &WSADat); // Ініціалізація WinSock
// 0x0202 - версія WinSock. Може бути 1.0, 1.1, 2.0, 2.2
// WSADat - структура, куди будуть занесені рез. ініціалізації
gethostname(PCName, 30); // Отримання імені поточного ПК
sin.sin_family = AF_INET; // Тип адреси
sin.sin_addr.s_addr = inet_addr(IP); // IP-адреса серверу (при створенні серверу 0)
sin.sin_port = htons(2803); // Номер порту сервера
Sock = socket(AF_INET, SOCK_STREAM, 0); // Створення сокету
// ***** Підключення до серверу
cout << "Connecting to server..." << endl;
if (connect(Sock, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR) {
cout << "Error of connecting!\n";
goto End; }
send(Sock, PCName, strlen(PCName) + 1, 0); // Відправка імені комп'ютера (клієнта)
recv(Sock, ServerName, 30, 0); // Отримання імені сервера
cout << "Connecting to \"" << ServerName << "\" is ready!" << endl;
// Відправка повідомлення серверу
cout<<"введіть масив А\n"; //Ініціалізація масиву А
for (i=0;i<4;i++){
cin>>a[i]; }
cout<<"введіть масив B\n"; //Ініціалізація масиву В
for (i=4;i<8;i++){
cin>>a[i]; }
if (send(Sock, a, strlen(a) + 1, 0) != SOCKET_ERROR) cout << "Sent!\n";
else cout << "Error of sending!\n";
cout << endl;
recv(Sock,Message, 42, 0); // Отримання імені сервера
for (i=1;i<3;i++){cout<<Message;cin.get();}
End: // Закриття сокетів і завершення роботи с WinSock
closesocket(Sock);
WSACleanup();
getch();
}
Лістинг програми сервера
#include <iostream.h>
# include <stdio.h>
#include <windows.h>
#include <conio.h>
char flag[2]="0";
#pragma comment (lib, "ws2_32.lib")
#pragma comment (lib, "mswsock.lib")
int flag1=0;
int porivn (char Mes[8])
{int i=0,flag=1;
for (i=0;i<4;i++){
if (Mes[i]!=Mes[i+4]) flag=0;
}
if (flag==1) {printf("%s","da");flag1=1;};
cout<<endl;
return 0;
}
int perestX(char Mes[8])
{ char a;
int i=0;
for (i=0;i<2;i++){
a=Mes[4+i];
Mes[4+i]=Mes[6+i];
Mes[6+i]=a;}
return 0;
}
int perestY(char Mes[8])
{ char a;
int i=0;
for (i=0;i<2;i++){
a=Mes[4+i];
Mes[4+i]=Mes[5+i];
Mes[5+i]=a;
i++;}
return 0;
}
void main(void) {
char PCName [30], ClientName[30],Message[200];
char ne[42]={'м','а','т','р','и','ц','і',' ','і','з','о','м','о','р','ф','н','і','!',' ',' ',' '};
char nr[42]={'м','а','т','р','и','ц','і',' ','н','е',' ','і','з','о','м','о','р','ф','н','і','!'};
int i,j;
WSAData WSADat; // Властивості WinSock (результат функції WSAStartup)
sockaddr_in sin; // Властивості(адреса) сокету, що створюється
SOCKET Sock, Client; // Серверний и клієнтський сокети
WSAStartup(0x0202,&WSADat); // Ініціалізація WinSock
// 0x0202 - версія WinSock. Може бути 1.0, 1.1, 2.0, 2.2
// WSADat - структура, куди будуть занесені рез. ініціалізації
gethostname(PCName, 30); // Отримання імені поточного ПК
sin.sin_family = AF_INET; // Тип адреси
sin.sin_addr.s_addr = 0; // IP-адреса сервера (при створенні сервера 0)
sin.sin_port = htons(2803); // Номер порту сервера
Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Створення сокету
bind(Sock, (sockaddr*)&sin, sizeof(sin)); // Зв’язування створеного сокету з адресою sin
// ***** Очікування клієнта
cout << "Wait of client..." << endl;
listen(Sock, SOMAXCONN); // Прослуховування сокету сервером (для підключення клієнта)
Client = accept(Sock, (sockaddr*)&sin, 0); // Очікування клієнту
recv(Client, ClientName, 30, 0); // Отримання імені компьютера клієнту
send(Client, PCName, strlen(PCName) + 1, 0); // Відправлення імені компьютеру (серверу)
// Прийом повідомлення від клієнта*/
if (recv(Client, Message, 200, 0) != SOCKET_ERROR) {
cout << "Massiv A" << endl;
for (i=0;i<4;i++){
cout<<Message[i]<<"\t";
if (i==1) cout <<endl;
}cout<<endl;
cout << "Massiv B" << endl;
for (i=4;i<8;i++){
cout<<Message[i]<<"\t";
if (i==5) cout <<endl;
}cout<<endl;
porivn(Message);
perestX(Message);
porivn(Message);
perestY(Message);
porivn(Message);
cin.get();
}
if (flag1==1){
if (send(Client, ne, strlen(ne) + 1, 0) != SOCKET_ERROR) cout << "Sent!\n";
cin.get();
}
else {
if (send(Client, nr, strlen(nr) + 1, 0) != SOCKET_ERROR) cout << "Sent!\n";
else {cout << "Error of sending!\n";
cin.get();
}
}
// Закриття сокетів і завершення роботи з WinSock
closesocket(Sock);
closesocket(Client);
WSACleanup();
}
- Методичні вказівки
- "Паралельні та розподілені обчислення"
- М.Кривий Ріг
- Основні вимоги та загальні методичні вказівки до виконання лабораторних робіт
- Лабораторна робота №1 Тема: «Імітація процесу розпаралелювання обчислення суми, добутку, матриць та знаходження коефіцієнтів характеристичного поліному»
- Концепція необмеженого паралелізму
- Приклад:
- Приклад виконання задачі для імітації розпаралелення процесу додавання двох матриць 2х2
- Звіт повинен містити:
- Контрольні питання:
- Лабораторна робота №2 Тема: «Розпаралелювання обчислення суми десяти чисел»
- Хід роботи
- Для восьми чисел:
- Для дев’яти чисел:
- Особливості програмного інтерфейсу потоків
- Створення потоків у Win32 арі
- Завершення потоків у Win32 арі
- Приєднання потоків у Win32 арі
- Приклад програми для знаходження суми 8-ми чисел за допомогою процесів без розпаралелення
- Звіт повинен містити:
- Контрольні питання:
- Лабораторна робота №3 Тема: «Розпаралелювання обчислення суми, добутку матриць та знаходження коефіцієнтів характеристичного поліному»
- Приклад виконання задачі розпаралелювання процесу додавання двох матриць 2х2
- Звіт повинен містити:
- Контрольні питання:
- Лабораторна робота №4 Тема: «Розпаралелювання процесу сортування масивів даних»
- Теоретичні відомості Мютекси
- Правила спрощеного паралелізму
- Приклад програми процесу сортування масиву даних
- Звіт повинен містити:
- Контрольні питання:
- Приклад виконання програми
- Звіт повинен містити:
- Контрольні питання:
- Література
- Додаток а
- "Паралельні та розподілені обчислення"
- 6.050102 «Комп’ютерні системи та мережі»