logo
делать №5

Приклад виконання задачі розпаралелювання процесу додавання двох матриць 2х2

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

#include <windows.h> //Підключення бібліотек

#include <process.h>

#include <iostream.h>

#include <conio.h>

#include <vcl.h>

int number1 = 9,number2 = 1,numb=0; //Змінні

int a1,b1;

unsigned tid;

HANDLE hThreads[10],Thread[3];

DWORD res;

char *array[100];

int mem[12],a[4],b[4],i=0,j=0,k=0;

unsigned __stdcall Sum( void * num) // Функція потоку

{ k+=1;

mem[k]=a1+b1;

return 0;

};

unsigned __stdcall Umn( void * num) // Функція потоку

{ k+=1;

mem[k]=a1*b1;

cout<<mem[k]<<endl;

return 0;

};

int main()

{ SetConsoleOutputCP(1251); //Використання кодування 1251

cout<<"vvedite massiv A\n"; //Ініціалізація масиву А

for (i=0;i<4;i++){

cin>>a[i];

}

cout<<"vvedite massiv B\n"; //Ініціалізація масиву В

for (i=0;i<4;i++){

cin>>b[i];

}

cout<<"A"; //Виведення масиву А

cout<<endl;

for (i=0;i<4;i++){

cout<<a[i]<<"\t";

if (i==1) cout<<endl;

}

cout<<endl;

cout<<"B"; //Виведення масиву В

cout<<endl;

for (i=0;i<4;i++){

cout<<b[i]<<"\t";

if (i==1) cout<<endl;

}

cout<<endl;

a1=a[0];b1=b[0];

//Створення потоків, що виконують функції процесорів

Thread[0] = (HANDLE)_beginthreadex(NULL, 0, Umn, (void *)++number1, 0, &tid);

Sleep(10);

a1=a[1];b1=b[2];

Thread[1] = (HANDLE)_beginthreadex(NULL, 0, Umn, (void *)++number2, 0, &tid);

Sleep(10);

a1=a[2];b1=b[0];

Thread[2] = (HANDLE)_beginthreadex(NULL, 0, Umn, (void *)++number2, 0, &tid);

Sleep(10);

a1=a[3];b1=b[2];

Thread[3] = (HANDLE)_beginthreadex(NULL, 0, Umn, (void *)++number2, 0, &tid);

Sleep(10);

//Очікування завершення останнього потоку

if (WaitForSingleObject(Thread[3], INFINITE) != WAIT_FAILED) {

cout<<"Потоки завершили виконання" <<endl;}

//Завершення потоків

CloseHandle(Thread[0]);

CloseHandle(Thread[1]);

CloseHandle(Thread[2]);

CloseHandle(Thread[3]);

a1=a[0];b1=b[1];

Thread[0] = (HANDLE)_beginthreadex(NULL, 0, Umn, (void *)++number1, 0, &tid);

Sleep(10);

a1=a[1];b1=b[3];

Thread[1] = (HANDLE)_beginthreadex(NULL, 0, Umn, (void *)++number2, 0, &tid);

Sleep(10);

a1=a[2];b1=b[1];

Thread[2] = (HANDLE)_beginthreadex(NULL, 0, Umn, (void *)++number2, 0, &tid);

Sleep(10);

a1=a[3];b1=b[3];

Thread[3] = (HANDLE)_beginthreadex(NULL, 0, Umn, (void *)++number2, 0, &tid);

Sleep(10);

if (WaitForSingleObject(Thread[3], INFINITE) != WAIT_FAILED) {

cout<<"Потоки завершили виконання" <<endl;}

CloseHandle(Thread[0]);

CloseHandle(Thread[1]);

CloseHandle(Thread[2]);

CloseHandle(Thread[3]);

a1=mem[1];b1=mem[2];

Thread[0] = (HANDLE)_beginthreadex(NULL, 0, Sum, (void *)++number1, 0, &tid);

Sleep(10);

a1=mem[5];b1=mem[6];

Thread[1] = (HANDLE)_beginthreadex(NULL, 0, Sum, (void *)++number2, 0, &tid);

Sleep(10);

a1=mem[3];b1=mem[4];

Thread[2] = (HANDLE)_beginthreadex(NULL, 0, Sum, (void *)++number2, 0, &tid);

Sleep(10);

a1=mem[7];b1=mem[8];

Thread[3] = (HANDLE)_beginthreadex(NULL, 0, Sum, (void *)++number2, 0, &tid);

Sleep(10);

if (WaitForSingleObject(Thread[3], INFINITE) != WAIT_FAILED) {

cout<<"Потоки завершили виконання" <<endl;}

CloseHandle(Thread[0]);

CloseHandle(Thread[1]);

CloseHandle(Thread[2]);

CloseHandle(Thread[3]);

//Виведення результату

Sleep(100);

for (i=9;i<13;i++){

cout<<mem[i]<<"\t";

if (i==10) cout<<endl;

}

getch();

return 0;

}

Дана програма виконує знаходження добутку матриць, в якості процесорів використовуючи потоки. Використано такі змінні:

Рисунок 3.1 – Схема розпаралелення процесу

На рисунку 3.1 показано процес розпаралелювання. В першому та другому ярусі всі чотири процесори виконують функцію множення, в третьому — додавання. Як видно з рисунку при виконанні задачі не виникає конфліктів в пам’яті.

На рисунку 3.2 проілюстровано виконання програми.

В даній програмі виконуються наступні пункти для кожного ярусу:

Створюємо потоки Thread[N] = (HANDLE)_beginthreadex(NULL, 0, Umn, 0, 0, &tid);

Чекаємо завершення операції (Sleep(10);)

Чекаємо завершення потоків, та закриваємо їх :

if (WaitForSingleObject(Thread[3], INFINITE) != WAIT_FAILED) {

cout<<"Потоки завершили виконання"<<endl;}

CloseHandle(Thread[0]);

CloseHandle(Thread[1]);

CloseHandle(Thread[2]);

CloseHandle(Thread[3]);

Аналогічні операції виконуємо для кожного ярусу (рисунок 3.2).

Програма має дві функції Sum — для для знаходження суми, та Umn — для знаходження добутку потоками. Дані функції імітують команди АЛП.