You are on page 1of 6

Прізвище: Гончарук

Ім'я: Павло
Група: КН-309
Варіант: 5

Інститут: ІКНІ
Кафедра: САПР
Дисципліна: Технології розподілених систем та паралельних обчислень
Перевірив: Фармага І.В.

ЗВІТ
до розрахункової роботи
на тему “Розроблення паралельних процедур обчислень засобами МРІ”

Мета роботи: Ознайомитись з методами організації паралельного множення матриці


на вектор чи на матрицю та розробити паралельну програму з використанням технології
MPI.

Короткі теоретичні відомості:

Матриці та операції над ними широко використовуються при математичному


моделюванні найрізноманітніших процесів, явищ і систем. Матричні обчислення складають
основу багатьох наукових і інженерних розрахунків.
Враховуючи важливість ефективного виконання матричних обчислень багато
стандартних бібліотек програм містять процедури для різних матричних операцій. Об'єм
програмного забезпечення для операцій над матрицями постійно збільшується -
розробляються нові оптимальні структури даних для зберігання матриць спеціального типу
(трикутних, стрічкових, розріджених тощо), створюються різні високоефективні машинно-
залежні реалізації алгоритмів, проводяться теоретичні дослідження для пошуку швидших
методів матричних обчислень.
Будучи обчислювально трудомісткими, матричні обчислення є класичною областю
застосування паралельних обчислень. З одного боку, використання високопродуктивних
багатопроцесорних систем дозволяє істотно підвищити складність завдань, які
розв’язуються. З іншого боку, через своє достатньо просте формулювання матричні операції
надають прекрасну можливість для демонстрації багатьох прийомів і методів паралельного
програмування.
У даній роботі проведено аналіз окремих методів паралельних обчислень для операції
з матрицями множення.

Індивідуальне завдання:
Хід роботи:

Декомпозиція:

Рис.1 Декомпозиція виразу

Рис.2 Схема розбиття матриці


Код програми:

#include <iostream>
#include <mpi.h>
#include<vector>
#include<random>
#define ROW 7
#define COL 14
using namespace std;

class Random
{
public:
static int get_random_number()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> distr(1, 3);
return distr(gen);
}
static void generate_random_matrix(double* A,int n)
{
for(int i=0;i<n;i++)
{
A[i]=get_random_number();
}
}
};

void InitializeData(double *a,int m,int n,int p,int rank) {


if(rank==0)
Random::generate_random_matrix(a,m*n);
}

void PrintMatrix(double *a,int m,int n)


{
int counter=0;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
cout<<a[counter]<<" ";
counter++;
}
cout<<endl;
}
}

void MultiplyMatrix(double *a,double*b,double *c,int m,int n,int p,int rank)


{
double *aa=new double[m*n/p];
double *cc=new double[m*n/p];
int sum=0;
MPI_Scatter(a, m*n/p, MPI_DOUBLE, aa, m*n/p, MPI_DOUBLE,0,MPI_COMM_WORLD);

MPI_Bcast(b, m*n, MPI_DOUBLE, 0, MPI_COMM_WORLD);


MPI_Barrier(MPI_COMM_WORLD);

for (int i = 0; i < n; i++)


{
for (int j = 0; j < m; j++)
{
sum = sum + aa[j]*b[m*j+i];
}
cc[i] = sum;
sum = 0;
}

MPI_Gather(cc, m*n/p, MPI_DOUBLE, c, m*n/p, MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);

if(rank==0)
{
PrintMatrix(c,m,n);
}
}

void MultiplyRowOnMatrix(double *a,double*b,double *c,int m,int n,int p,int


rank)
{
if(rank==0)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
c[i]+=a[j]*b[m*j+i];
}
}
}
}

void SumArray(double *a,double*b,double*c,int m,int n,int rank,int p)


{
double *aa=new double[m*n/p];
double *cc=new double[m*n/p];
double *bb=new double[m*n/p];
MPI_Scatter(a, m*n/p, MPI_DOUBLE, aa, m*n/p, MPI_DOUBLE,0,MPI_COMM_WORLD);

MPI_Scatter(b, m*n/p, MPI_DOUBLE, bb, m*n/p, MPI_DOUBLE,0,MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);

for (int j = 0; j < m*n/p; j++)


{
cc[j] = aa[j]+bb[j];
}

MPI_Gather(cc, m*n/p, MPI_DOUBLE, c, m*n/p, MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);

if(rank==0)
{
PrintMatrix(c,m,n);
}
}
void SubtractArray(double *a,double*b,double*c,int m,int n,int rank,int p)
{
double *aa=new double[m*n/p];
double *cc=new double[m*n/p];
double *bb=new double[m*n/p];
MPI_Scatter(a, m*n/p, MPI_DOUBLE, aa, m*n/p, MPI_DOUBLE,0,MPI_COMM_WORLD);

MPI_Scatter(b, m*n/p, MPI_DOUBLE, bb, m*n/p, MPI_DOUBLE,0,MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);

for (int j = 0; j < m*n/p; j++)


{
cc[j] = aa[j]-bb[j];
}

MPI_Gather(cc, m*n/p, MPI_DOUBLE, c, m*n/p, MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);

if(rank==0)
{
PrintMatrix(c,m,n);
}
}

void MultiplyByConst(double* a,double *c,double val,int rank,int p,int n,int m)


{
double *aa=new double[m*n/p];
double *cc=new double[m*n/p];
MPI_Scatter(a, m*n/p, MPI_DOUBLE, aa, m*n/p, MPI_DOUBLE,0,MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);

for(int i=0;i<m*n/p;i++)
{
cc[i]=aa[i]*val;
}
MPI_Gather(cc, m*n/p, MPI_DOUBLE, c, m*n/p, MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);

if(rank==0)
{
PrintMatrix(c,m,n);
}

void AddConst(double *a,double *c,double val,int rank,int p,int n,int m)


{
double *aa=new double[m*n/p];
double *cc=new double[m*n/p];
MPI_Scatter(a, m*n/p, MPI_DOUBLE, aa, m*n/p, MPI_DOUBLE,0,MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);

for(int i=0;i<m*n/p;i++)
{
cc[i]=aa[i]+val;
}
MPI_Gather(cc, m*n/p, MPI_DOUBLE, c, m*n/p, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);

if(rank==0)
{
PrintMatrix(c,m,n);
}
}

Результат виконання:

Рис.3 Результат виконання програми

Висновок: В результаті виконання даної розрахункової роботи я ознайомився з


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

You might also like