You are on page 1of 9

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

ІНСТИТУТ КОМПЮТЕРНИХ НАУК ТА ІНФОРМАЦІЙНИХ ТЕХНОЛОГІЙ


НАЦІОНАЛЬНОГО УНІВЕРСИТЕТУ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»

Кафедра САП

ЗВІТ

до розрахунково-графічної роботи

на тему: “Розроблення паралельних процедур обчислень засобами MPI”


з дисципліни: “ Технології розподілених систем та паралельних обчислень”

Виконав:
студент групи КН-306
Герус В. С.
Прийняв:
Доцент кафедри САП
Фармага І. В.

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

Індивідуальне завдання:
1. Розробити схему інформаційної взаємодії під-задач при перемноженні матриць
згідно заданого (варіанту) типу розбиття та вибираємо ваш варіант з лабораторної роботи №2
і відповідно до типу матриць вибираємо розбивання.
2. Розбити структурну схему алгоритму перемноження матриць для заданого розбиття.
3. Розробити структурну схему алгоритму перемноження матриць для варіанту з
лабораторної роботи №2, визначивши типи розбиття для досягнення максимально
ефективного алгоритму обчислень.
4. Обчислити кількість операцій та розмір даних для кожного процесора.
5. Встановити МРІ у розподіленій системі, отриманій в лабораторній роботі №4.
Приклад встановлення MPI для Windows наведено у додатку 1.
6. Розробити програму для перемноження матриць з використанням МРІ.
7. Зробити висновок про ефективність застосування заданого типу розбиття для
поставленої задачі.
Табл. 1. Індивідуальне завдання.
№ Розмір матриці Тип розбиття Кількість процесорів
5 140 70 блокове 7

Хід виконання:
Крок 1. Спочатку встановив фреймворк MPI для Java: MPJ_Express. Встановив
системну зміну MPJ_HOME, щоб далі використовувати MPI при запуску програм.

Рис. 1. Добавлення системної зміни MPJ_HOME.


Крок 2. Розробив схему інформаційної взаємодії між процесами згідного свого
варіанту розбиття та алгоритму множення.

Рис. 2. Схема інформаційної взаємодії та алгоритм множення.

Розрахував кількість операцій та розмір блоку:


Для правильного обрахунку потрібно зробити розбив матриці на 7 (кількість
процесорів) блоків тому кількість стовбців і рядків мають бути множниками числа 7. Виконав
розбиття матриці на 7 рядків та 1 стовбці. Розмір блоку даних є 140 / 7 на 70 / 1, тобто 20 на
70. В такому випадку кожен блок даних містить 20 * 70 = 1400 значень. Тому кількість
операцій на кожному процесорі дорівнюватиме 1400.

Крок 3. Розробив програму для перемноження матриць, що представ в додатку А


використовуючи засоби МРІ та запустив на виконання після чого отримав відповідний
результат.

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

Крок 4. Реалізував перемноження матриць для варіанту з лабораторної роботи №2, що


представив у Додатку Б та запустив на виконання.

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


Крок 5. Встановив МРІ у розподіленій системі, отриманій в лабораторній роботі №4 та
розпочав виконання завдання.
5.1. Спочатку для того щоб мати зв’язок між пристроями створив файл machines в якому
записав ip-адреси пристроїв.

Рис. 5. Записані ip-адреси пристроїв.

5.2. Скомпілював файл командою: javac –cp .;%MPJ_HOME%/lib/mpj.jar .

Рис. 6. Компіляція файлу.

5.3. Запустив демони на обох пристроях командою: mpjdaemon.bat –boot .

Рис. 7. Запуск демонів.

5.4. Запустив на виконання програму командою: mpjrun -np 7 -dev niodev та отримав
відповідний результат.

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

Висновок: під час виконання розрахунково-графічної роботи ознайомився з методами


організації паралельного множення матриці на вектор чи на матрицю. Розробив паралельну
програму з використанням технології MPI, що реалізує множення матриць згідно
індивідуального варіанту. Крім того виконав реалізацію перемноження матриць для варіанту
з лабораторної роботи №2. Також встановив МРІ у розподіленій системі, отриманій в
лабораторній роботі №4 та виконав перемноження матриць на двох пристроях. Результати
виконання завдань представив у вигляді скріншотів.
Додаток А

1. Main.class:
public class Main {
public static int rows = 140, cols = 70;
public static void main(String[] args) {
new Calculator_one(rows, cols, args);
}
}

2. Calculator_one.class:
import mpi.*;
import java.util.Random;

public class Calculator_one {


private int rows, cols;
private String[] args;
private long start_t, end_t;
public Calculator_one(int rows, int cols, String[] args){
this.rows = rows;
this.cols = cols;
this.args = args;
this.process_run();
}
private void process_run() throws MPIException{
MPI.Init(this.args);
int prs_size = MPI.COMM_WORLD.Size(), prs_rank = MPI.COMM_WORLD.Rank();
int main_prs = 0;
float[] A = new float[this.rows * this.cols], B = new float[this.cols], C = new
float[this.rows];
if (prs_rank == main_prs) {
this.start_t = System.currentTimeMillis();
Random rand = new Random();
for (int i = 0; i < this.rows * this.cols; i++)
A[i] = rand.nextFloat();
for (int i = 0; i < this.cols; i++)
B[i] = rand.nextFloat();
}
float[] block = new float[this.rows * this.cols / prs_size];
MPI.COMM_WORLD.Scatter(A, 0, this.rows * this.cols / prs_size, MPI.FLOAT, block,
0, this.rows * this.cols / prs_size, MPI.FLOAT, 0);
MPI.COMM_WORLD.Bcast(B, 0, cols, MPI.FLOAT, 0);
float[] divC = new float[this.rows / prs_size];
for (int i = 0; i < this.rows / prs_size; i++)
for (int j = 0; j < this.cols; j++)
divC[i] += block[i * this.cols + j] * B[j];
MPI.COMM_WORLD.Gather(divC, 0, this.rows / prs_size, MPI.FLOAT, C, 0,
this.rows / prs_size, MPI.FLOAT, 0);
if (prs_rank == main_prs) {
this.end_t = System.currentTimeMillis();
System.out.println("RESULT VECTOR");
for (int i = 0; i < this.rows; i++)
System.out.print(C[i] + " ");
System.out.println("\nTime for calculating = " + (double) (this.end_t - this.start_t) /
1000 + " s");
float[] C_temp = new float[rows];
this.start_t = System.currentTimeMillis();
for (int i = 0; i < this.rows; i++) {
float s = 0.0f;
for (int j = 0; j < this.cols; j++)
s += A[i * this.cols + j] * B[j];
C_temp[i] = s;
}
this.end_t = System.currentTimeMillis();
System.out.println("RESULT VECTOR");
for (int i = 0; i < this.rows; i++)
System.out.print(C_temp[i] + " ");
System.out.println("\nTime for calculating = " + (double) (this.end_t - this.start_t) /
1000 + " s");
}
MPI.Finalize();
System.exit(0);
}
}
Додаток Б

1. Main.class:
public class Main {
public static int rows = 140, cols = 70;
public static void main(String[] args) {
//new Calculator_one(rows, cols, args);
new Calculator_two(rows, cols, args);
}
}

2. Calculator_two.class:
import mpi.*;
import java.util.Random;
public class Calculator_two {
private int rows, cols;
private String[] args;
public Calculator_two(int rows, int cols, String[] args){
this.rows = rows;
this.cols = cols;
this.args = args;
this.process_run();
}
private void process_run() throws MPIException {
MPI.Init(args);
int me = MPI.COMM_WORLD.Rank();
int size = MPI.COMM_WORLD.Size();
long start_t = System.currentTimeMillis();
float[] A = new float[rows * cols], A1 = new float[rows * cols], A2 = new float[rows *
cols];
float[] bi = new float[cols], c1 = new float[cols], b1 = new float[cols];
float[] B2 = new float[rows * cols], Cij = new float[rows * cols];
float[] b1_minus_c1 = new float[cols], C2_plus_B2 = new float[rows * cols];
float[] y1 = new float[rows], y2 = new float[rows], Y3 = new float[rows * rows],
Y3_pow2 = new float[rows * rows];
float[] y1T_Y3 = new float[rows], y1T_Y3_plus_y2 = new float[rows];
float[] y2_Y3 = new float[rows], y1_y2T = new float[rows * rows], y1_y2t_Y3_pow2
= new float[rows * rows], y1_y2t_Y3_pow2_y2 = new float[rows];
float[] y2_Y3_plus_y1_plus_y1_y2t_Y3_pow2_y2 = new float[rows];
if(me == 0){
this.Random_set(A);
this.Random_set(A1);
this.Random_set(A2);
this.Random_set(B2);
this.Random_set(c1);
this.Random_set(b1);
for (int i = 0; i < cols; i++)
bi[i] = (float) (5 * Math.pow(i + 1, 3));
}
matrixVectorMultiplication(A, bi, rows, cols, me, size, y1);
if(me == 0)
for(int i = 0; i < cols; i++)
b1_minus_c1[i] = 5 * bi[i] - c1[i];
matrixVectorMultiplication(A1, b1_minus_c1, rows, cols, me, size, y2);
if(me == 0){
for(int i = 0; i < rows; i++)
for(int j = 0; j < cols; j++)
Cij[i * cols + j] = (float) (1 / (Math.pow(i + 1, 2) + j));
for(int i = 0; i < rows; i++)
for(int j = 0; j < cols; j++)
C2_plus_B2[i * cols + j] = B2[i * cols + j] + 10 * Cij[i * cols + j];
}
matrixMultiplication(A2, C2_plus_B2, rows, cols, me, size, Y3);
matrixMultiplication(Y3, Y3, rows, rows, me, size, Y3_pow2);
matrixVectorMultiplication(Y3, y1, rows, rows, me, size, y1T_Y3);
if(me == 0)
for(int i = 0; i < rows; i++)
y1T_Y3_plus_y2[i] = y1T_Y3[i] + y2[i];
matrixVectorMultiplication(Y3, y2, rows, rows, me, size, y2_Y3);
if(me == 0)
for(int i = 0; i < rows; i++)
for(int j = 0; j < rows; j++)
y1_y2T[i * rows + j] = y1[i] * y2[j];
matrixMultiplication(y1_y2T, Y3_pow2, rows, rows, me, size, y1_y2t_Y3_pow2);
matrixVectorMultiplication(y1_y2t_Y3_pow2, y2, rows, rows, me,
size,y1_y2t_Y3_pow2_y2);
if(me == 0){
for(int i = 0; i < rows; i++)
y2_Y3_plus_y1_plus_y1_y2t_Y3_pow2_y2[i] = y2_Y3[i] + y1[i] +
y1_y2t_Y3_pow2_y2[i];
float result = 0;
for(int i = 0; i < rows; i++)
result += y1T_Y3_plus_y2[i] * y2_Y3_plus_y1_plus_y1_y2t_Y3_pow2_y2[i];
long end_t = System.currentTimeMillis();
System.out.println("\nRESULT: " + result);
System.out.println("Time for calculating = " + (double) (end_t - start_t) / 1000 + "
s\n");
}
MPI.Finalize();
System.exit(0);
}
private static void matrixVectorMultiplication(float[] matrix, float[] vector, int rows, int
cols, int me, int size, float[] result) {
float[] matrixBlock = new float[rows * cols / size];
MPI.COMM_WORLD.Scatter(matrix, 0, rows * cols / size, MPI.FLOAT, matrixBlock,
0, rows * cols / size, MPI.FLOAT, 0);
MPI.COMM_WORLD.Bcast(vector, 0, cols, MPI.FLOAT, 0);
float[] partialResult = new float[rows / size];
for (int i = 0; i < rows / size; i++) {
for (int j = 0; j < cols; j++) {
partialResult[i] += matrixBlock[i * cols + j] * vector[j];
}
}
MPI.COMM_WORLD.Gather(partialResult, 0, rows / size, MPI.FLOAT, result, 0, rows
/ size, MPI.FLOAT, 0);
if (me == 0) {
for (int i = 1; i < size; i++) {
for (int j = 0; j < rows / size; j++) {
result[i * (rows / size) + j] = partialResult[j];
}
}
}
}
private static void matrixMultiplication(float[] A, float[] B, int rows, int cols, int prs_rank,
int prs_size, float[] result) {
int nRowsA = rows;
int nColsA = cols;
int nColsB = rows;
int rowsPerProcess = nRowsA / prs_size;
int colsPerProcess = nColsA;
float[] C = new float[rowsPerProcess * nColsB];
MPI.COMM_WORLD.Scatter(A, 0, rowsPerProcess * nColsA, MPI.FLOAT, A, 0,
rowsPerProcess * nColsA, MPI.FLOAT, 0);
MPI.COMM_WORLD.Bcast(B, 0, nColsA * nColsB, MPI.FLOAT, 0);
for (int i = 0; i < rowsPerProcess; i++) {
for (int j = 0; j < nColsB; j++) {
float sum = 0;
for (int k = 0; k < nColsA; k++) {
sum += A[i * nColsA + k] * B[k * nColsB + j];
}
C[i * nColsB + j] = sum;
}
}
MPI.COMM_WORLD.Gather(C, 0, rowsPerProcess * nColsB, MPI.FLOAT, result, 0,
rowsPerProcess * nColsB, MPI.FLOAT, 0);
}
private void Random_set(float[] matrix){
Random rand = new Random();
for(int i = 0; i < matrix.length; i++)
matrix[i] = rand.nextFloat();
}
}

You might also like