batman
17
doc-lb.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
subject: ТВО
|
||||
doctype: ЛБ
|
||||
mentors:
|
||||
- name: Міщеряков Ю. В.
|
||||
degree: Професор кафедри СТ
|
||||
gender: m
|
||||
edu_program: &EDU КНТ
|
||||
university: ХНУРЕ
|
||||
authors:
|
||||
- name: Орлов О. С.
|
||||
# full_name_gen: Косач Лариси Петрівни
|
||||
course: 4
|
||||
edu: *EDU
|
||||
gender: m
|
||||
group: 22-1
|
||||
semester: 7
|
||||
variant: 9
|
||||
17
doc-pz.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
subject: ТВО
|
||||
doctype: ПЗ
|
||||
mentors:
|
||||
- name: Міщеряков Ю. В.
|
||||
degree: Професор кафедри СТ
|
||||
gender: m
|
||||
edu_program: &EDU КНТ
|
||||
university: ХНУРЕ
|
||||
authors:
|
||||
- name: Орлов О. С.
|
||||
# full_name_gen: Косач Лариси Петрівни
|
||||
course: 4
|
||||
edu: *EDU
|
||||
gender: m
|
||||
group: 22-1
|
||||
semester: 7
|
||||
variant: 9
|
||||
1
lab1
Submodule
BIN
lab2/ParaLab new version/ArraySortTask.dll
Normal file
BIN
lab2/ParaLab new version/BlockMatrixVectorTask.dll
Normal file
BIN
lab2/ParaLab new version/BubbleArraySortTask.dll
Normal file
BIN
lab2/ParaLab new version/CannonMatrixMultTask.dll
Normal file
BIN
lab2/ParaLab new version/ColumnwiseMatrixVectorTask.dll
Normal file
BIN
lab2/ParaLab new version/DifferentialEquationTask.dll
Normal file
BIN
lab2/ParaLab new version/DijkstraGraphTask.dll
Normal file
BIN
lab2/ParaLab new version/FloydGraphTask.dll
Normal file
BIN
lab2/ParaLab new version/FoxMatrixMultTask.dll
Normal file
BIN
lab2/ParaLab new version/GaussLinearTask.dll
Normal file
BIN
lab2/ParaLab new version/GaussSeidelTask.dll
Normal file
BIN
lab2/ParaLab new version/GradientsLinearTask.dll
Normal file
BIN
lab2/ParaLab new version/GraphProcessingTask.dll
Normal file
BIN
lab2/ParaLab new version/IndexOptimizationTask.dll
Normal file
BIN
lab2/ParaLab new version/LinearSystemTask.dll
Normal file
BIN
lab2/ParaLab new version/MatrixMultTask.dll
Normal file
BIN
lab2/ParaLab new version/MatrixVectorMultTask.dll
Normal file
BIN
lab2/ParaLab new version/NPlot.dll
Normal file
BIN
lab2/ParaLab new version/Old/ArraySortTask.dll
Normal file
BIN
lab2/ParaLab new version/Old/BubbleArraySortTask.dll
Normal file
BIN
lab2/ParaLab new version/Old/PlotComponents.dll
Normal file
BIN
lab2/ParaLab new version/OptimizationTask.dll
Normal file
BIN
lab2/ParaLab new version/ParaLab.exe
Normal file
7
lab2/ParaLab new version/ParaLab.exe.config
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup useLegacyV2RuntimeActivationPolicy="true">
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
||||
<requiredRuntime version="v4.0"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
BIN
lab2/ParaLab new version/ParaLab.pdb
Normal file
BIN
lab2/ParaLab new version/ParaLab.vshost.exe
Normal file
7
lab2/ParaLab new version/ParaLab.vshost.exe.config
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup useLegacyV2RuntimeActivationPolicy="true">
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
||||
<requiredRuntime version="v4.0"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
11
lab2/ParaLab new version/ParaLab.vshost.exe.manifest
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
BIN
lab2/ParaLab new version/ParaLabSDK.dll
Normal file
BIN
lab2/ParaLab new version/PlotComponents.dll
Normal file
BIN
lab2/ParaLab new version/PlotComponents1.dll
Normal file
BIN
lab2/ParaLab new version/PlotComponentsGDI.dll
Normal file
BIN
lab2/ParaLab new version/PrimGraphTask.dll
Normal file
BIN
lab2/ParaLab new version/QuickArraySortTask.dll
Normal file
BIN
lab2/ParaLab new version/RowwiseMatrixVectorTask.dll
Normal file
BIN
lab2/ParaLab new version/ShellArraySortTask.dll
Normal file
BIN
lab2/ParaLab new version/TapeMatrixMultTask.dll
Normal file
BIN
lab2/ParaLab new version/en-GB/ParaLab.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/ArraySortTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/BubbleArraySortTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/DijkstraGraphTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/FloydGraphTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/FoxMatrixMultTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/GaussLinearTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/GaussSeidelTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/GradientsLinearTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/GraphProcessingTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/LinearSystemTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/MatrixMultTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/OptimizationTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/ParaLab.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/ParaLabSDK.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/PrimGraphTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/QuickArraySortTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/ShellArraySortTask.resources.dll
Normal file
BIN
lab2/ParaLab new version/en-US/TapeMatrixMultTask.resources.dll
Normal file
8
lab2/bibl.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
metod:
|
||||
type: Book
|
||||
author: Міщеряков Ю. В., Хряпкін О. В., Міщеряков А. Ю. Яцик М. В.
|
||||
title: Методичні вказівки до лабораторного практикуму, розділу розробка паралельних програм засобами MPI, дисципліни Технології високопродуктивних обчислень для студентів усіх форм навчання, спеціальність F3 Комп'ютерні науки, освітньо-професійна програма Комп’ютерні науки та технології
|
||||
date: 2025
|
||||
publisher: ХНУРЕ
|
||||
location: Харків
|
||||
page-total: 237
|
||||
BIN
lab2/calculations.ods
Normal file
17
lab2/doc.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
subject: ТВО
|
||||
doctype: ЛБ
|
||||
mentors:
|
||||
- name: Міщеряков Ю. В.
|
||||
degree: Професор кафедри СТ
|
||||
gender: m
|
||||
edu_program: &EDU КНТ
|
||||
university: ХНУРЕ
|
||||
authors:
|
||||
- name: Орлов О. С.
|
||||
# full_name_gen: Косач Лариси Петрівни
|
||||
course: 4
|
||||
edu: *EDU
|
||||
gender: m
|
||||
group: 22-1
|
||||
semester: 7
|
||||
variant: 9
|
||||
BIN
lab2/n20p16.png
Normal file
|
After Width: | Height: | Size: 242 KiB |
BIN
lab2/n20p25.png
Normal file
|
After Width: | Height: | Size: 414 KiB |
BIN
lab2/n20p5.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
lab2/n20p8.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
lab2/paralab.tar.zst
Normal file
6157
lab2/ТВО_КНТ_22_1_Орлов_ЛБ2.pdf
Normal file
82
lab2/ТВО_КНТ_22_1_Орлов_ЛБ2.typ
Normal file
@@ -0,0 +1,82 @@
|
||||
#import "@local/nure:0.1.0": *
|
||||
|
||||
#show: pz-lb.with(
|
||||
..yaml("doc.yaml"),
|
||||
worknumber: 2,
|
||||
title: "ДОСЛІДЖЕННЯ КОМУНІКАЦІЙНОЇ ТРУДОМІСТКОСТІ ПАРАЛЕЛЬНИХ АЛГОРИТМІВ",
|
||||
bib_array: bytes(read("bibl.yml")),
|
||||
)
|
||||
|
||||
== Мета роботи
|
||||
#v(-spacing)
|
||||
Дослідити комунікаційну складність обчислювальної схеми в залежності від
|
||||
топології багатопроцесорної обчислювальної системи.
|
||||
|
||||
== Хід роботи
|
||||
#v(-spacing)
|
||||
|
||||
Завдання: розрахувати комунікаційну трудомісткість для паралельного розв'язання СЛАР за допомогою алгоритма Гауса.
|
||||
|
||||
Час передачі даних (теоритичний) $t_(d t)$ розрахуємо за формулою:
|
||||
$ t_(d t) = t_p + (m * t_d + t_a) * l $
|
||||
- $t_p$ - затримка (latency)
|
||||
- $t_d$ - час передачі одиниці даних по одному каналу зв'язку
|
||||
- $m$ - розмір елемента (використовуємо `double`, що на x86_64 займає 8 байт)
|
||||
Для метода Гауса у середовищі ParaLab можна застосувати тільки топологію "повний граф"
|
||||
через те що цей метод потребує постійної комунікації "один-до-всіх" (іншими
|
||||
словами, broadcast).
|
||||
За значення $t_p$ візьмемо $10*10^(-6) = 10 mu s$, за $1/t_d$ -- $100 * 1024^2 = #{ 100 * calc.pow(1024, 2) } approx 100 "MB"/s$, відповідно $t_d = 0.00000001 s = 10 n s$
|
||||
Візьмемо формулу для розрахунку комунікаційної трудомісткості, виведену у методичних вказівках для третьої практичної роботи @metod.
|
||||
Для легшої орієнтації, наведемо її ще раз у цій роботі:
|
||||
$ T_(d t) = (n - 1) * log_2p * (3alpha + w(n+2)/beta) $
|
||||
|
||||
Розрахуємо теоретичні показники комунікаційної трудомісткості для $n = 20$ та $p = 5,8,16,25$
|
||||
#let beta = 100 * calc.pow(1024, 2) // 100 MBytes
|
||||
#let alpha = decimal("0.00001") // 10 * 10^-6 seconds - 10 us
|
||||
#let w = 8 // 8 bytes - double size
|
||||
#let p = (5, 8, 16, 25)
|
||||
#let n = (20, 20, 20, 20)
|
||||
#let calculated = range(0, p.len()).map(i => {
|
||||
let elements = decimal(n.at(i))
|
||||
let log2nproc = decimal(calc.log(p.at(i), base: 2))
|
||||
// explanation: (n − 1) * log_2 p * (3a + w(n + 2)/beta) -- formula from 3rd practical methodicals
|
||||
return decimal(elements - 1) * log2nproc * (3 * alpha + (w * (elements + 2)) / decimal(beta))
|
||||
})
|
||||
|
||||
#figure(
|
||||
table(
|
||||
columns: 3,
|
||||
[$n$], [$p$], [$T_(d t)$ теоретичне],
|
||||
..range(0, p.len())
|
||||
.map(i => {
|
||||
(table.cell[#n.at(i)], table.cell[#p.at(i)], table.cell[#calc.round(calculated.at(i), digits: 6)])
|
||||
})
|
||||
.flatten(),
|
||||
),
|
||||
)
|
||||
|
||||
Запустимо розрахунки у середовищі виконання paralab. Отримуємо наступні результати для методу передачі повідомлень.
|
||||
#figure(image("n20p5.png", width: 80%), caption: [Результат для $n=20$, $p=5$])
|
||||
#figure(image("n20p8.png", width: 80%), caption: [Результат для $n=20$, $p=8$])
|
||||
#figure(image("n20p16.png", width: 80%), caption: [Результат для $n=20$, $p=16$])
|
||||
#figure(image("n20p25.png", width: 80%), caption: [Результат для $n=20$, $p=25$])
|
||||
|
||||
Зробимо порівняльну таблицю.
|
||||
#figure(table(
|
||||
columns: 2,
|
||||
[$T_(d t)$ теоретичне], [$T_(d t)$ практичне],
|
||||
..range(0, p.len())
|
||||
.map(i => {
|
||||
(table.cell[#calc.round(calculated.at(i), digits: 6)],) * 2
|
||||
})
|
||||
.flatten(),
|
||||
))
|
||||
|
||||
Можемо побачити, що результати повністю співпадають.
|
||||
Це означає, що створена модель є достовірною і може використовуватись для точних розрахунків часу комунікаційної трудомісткості.
|
||||
|
||||
== Висновки
|
||||
#v(-spacing)
|
||||
|
||||
Було досліджено комунікаційну складність обчислювальної схеми в залежності від
|
||||
топології багатопроцесорної обчислювальної системи.
|
||||
2
lab3/.clangd
Normal file
@@ -0,0 +1,2 @@
|
||||
CompileFlags:
|
||||
Add: [-Ivendor/openmpi-5.0.9/ompi/include]
|
||||
17
lab3/doc.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
subject: ТВО
|
||||
doctype: ЛБ
|
||||
mentors:
|
||||
- name: Міщеряков Ю. В.
|
||||
degree: Професор кафедри СТ
|
||||
gender: m
|
||||
edu_program: &EDU КНТ
|
||||
university: ХНУРЕ
|
||||
authors:
|
||||
- name: Орлов О. С.
|
||||
# full_name_gen: Косач Лариси Петрівни
|
||||
course: 4
|
||||
edu: *EDU
|
||||
gender: m
|
||||
group: 22-1
|
||||
semester: 7
|
||||
variant: 9
|
||||
125
lab3/main.c
Normal file
@@ -0,0 +1,125 @@
|
||||
#include <mpi.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#define N 25000
|
||||
|
||||
int compare_doubles(const void *a, const void *b) {
|
||||
double arg1 = *(const double *)a;
|
||||
double arg2 = *(const double *)b;
|
||||
if (arg1 < arg2)
|
||||
return -1;
|
||||
if (arg1 > arg2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void compare_split(int n_local, double *local_data, double *recv_data,
|
||||
int keep_small) {
|
||||
int i = 0, j = 0, k = 0;
|
||||
|
||||
double *merged = (double *)malloc(2 * n_local * sizeof(double));
|
||||
while (i < n_local && j < n_local) {
|
||||
if (local_data[i] < recv_data[j])
|
||||
merged[k++] = local_data[i++];
|
||||
else
|
||||
merged[k++] = recv_data[j++];
|
||||
}
|
||||
while (i < n_local)
|
||||
merged[k++] = local_data[i++];
|
||||
while (j < n_local)
|
||||
merged[k++] = recv_data[j++];
|
||||
|
||||
if (keep_small) {
|
||||
for (i = 0; i < n_local; i++)
|
||||
local_data[i] = merged[i];
|
||||
} else {
|
||||
for (i = 0; i < n_local; i++)
|
||||
local_data[i] = merged[n_local + i];
|
||||
}
|
||||
free(merged);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int rank, size;
|
||||
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &size);
|
||||
|
||||
int n_local = N / size;
|
||||
double *local_data = (double *)malloc(n_local * sizeof(double));
|
||||
double *recv_data = (double *)malloc(n_local * sizeof(double));
|
||||
|
||||
srand(time(NULL) + rank);
|
||||
for (int i = 0; i < n_local; i++) {
|
||||
local_data[i] = (double)(rand() % 1001);
|
||||
}
|
||||
|
||||
double start_time = MPI_Wtime();
|
||||
|
||||
qsort(local_data, n_local, sizeof(double), compare_doubles);
|
||||
|
||||
for (int step = 0; step < size; step++) {
|
||||
int partner = -1;
|
||||
|
||||
if (step % 2 == 0) {
|
||||
if (rank % 2 == 0)
|
||||
partner = rank + 1;
|
||||
else
|
||||
partner = rank - 1;
|
||||
} else {
|
||||
if (rank % 2 != 0)
|
||||
partner = rank + 1;
|
||||
else
|
||||
partner = rank - 1;
|
||||
}
|
||||
|
||||
if (partner >= 0 && partner < size) {
|
||||
MPI_Sendrecv(local_data, n_local, MPI_DOUBLE, partner, 0, recv_data,
|
||||
n_local, MPI_DOUBLE, partner, 0, MPI_COMM_WORLD,
|
||||
MPI_STATUS_IGNORE);
|
||||
|
||||
if (rank < partner) {
|
||||
compare_split(n_local, local_data, recv_data, 1);
|
||||
} else {
|
||||
compare_split(n_local, local_data, recv_data, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double end_time = MPI_Wtime();
|
||||
|
||||
double *global_data = NULL;
|
||||
if (rank == 0) {
|
||||
global_data = (double *)malloc(N * sizeof(double));
|
||||
}
|
||||
|
||||
MPI_Gather(local_data, n_local, MPI_DOUBLE, global_data, n_local, MPI_DOUBLE,
|
||||
0, MPI_COMM_WORLD);
|
||||
|
||||
if (rank == 0) {
|
||||
printf("Processes: %d\n", size);
|
||||
printf("N: %d\n", N);
|
||||
printf("Time: %f s\n", end_time - start_time);
|
||||
|
||||
int sorted = 1;
|
||||
for (int i = 1; i < N; i++) {
|
||||
double next_el = global_data[i];
|
||||
double current_el = global_data[i - 1];
|
||||
// printf("[%.0f %.0f] i:%d", current_el, next_el, i);
|
||||
if (current_el > next_el) {
|
||||
sorted = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("Verification: %s\n", sorted ? "OK" : "FAILED");
|
||||
free(global_data);
|
||||
}
|
||||
|
||||
free(local_data);
|
||||
free(recv_data);
|
||||
|
||||
MPI_Finalize();
|
||||
return 0;
|
||||
}
|
||||
BIN
lab3/proc1.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
lab3/proc2.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
lab3/proc4.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
4318
lab3/ТВО_КНТ_22_1_Орлов_ЛБ3.pdf
Normal file
100
lab3/ТВО_КНТ_22_1_Орлов_ЛБ3.typ
Normal file
@@ -0,0 +1,100 @@
|
||||
#import "@local/nure:0.1.0": *
|
||||
|
||||
#show: pz-lb.with(
|
||||
..yaml("doc.yaml"),
|
||||
worknumber: 3,
|
||||
title: "ПАРАЛЕЛЬНЕ ПРОГРАМУВАННЯ З ВИКОРИСТАННЯМ ТЕХНОЛОГІЇ MPI",
|
||||
)
|
||||
|
||||
== Мета роботи
|
||||
#v(-spacing)
|
||||
Ознайомлення з принципами роботи паралельних MPI-програм, засобами їх
|
||||
розробки і запуску.
|
||||
|
||||
== Хід роботи
|
||||
#v(-spacing)
|
||||
|
||||
Варіант розраховується за формулою: $S = (14 - N)^2 dot 1000$, де $N$ — номер студента у списку.
|
||||
Для $N = 9$:
|
||||
$ S = (14 - 9)^2 dot 1000 = 5^2 dot 1000 = 25 000 $
|
||||
|
||||
Топологія «Кільце» характеризується тим, що кожен вузол з'єднаний рівно з двома сусідніми.
|
||||
Основні характеристики топології «Кільце» для $p$ процесорів:
|
||||
- діаметр: $p/2$;
|
||||
- зв'язність: 2;
|
||||
- ширина бінарного розподілу: 2;
|
||||
- вартість: $p$.
|
||||
|
||||
Для сортування на кільцевій топології обрано алгоритм парного-непарного
|
||||
сортування (Odd-Even Transposition Sort). Масив розбивається на $p$ частин. На
|
||||
кожній ітерації процеси обмінюються даними із сусідами (парні з непарними,
|
||||
потім навпаки), зливають отримані масиви та залишають собі відповідну (старшу
|
||||
або молодшу) частину даних.
|
||||
|
||||
Комунікаційна трудомісткість:
|
||||
Алгоритм потребує $p$ етапів обміну. На кожному етапі передається блок розміром $N/p$.
|
||||
$ T_"comm" approx p dot (t_s + frac(N, p) dot t_w) $
|
||||
де $t_s$ — латентність, $t_w$ — час передачі одного слова.
|
||||
Оскільки у кільці обмін відбувається лише з безпосередніми сусідами, конфлікти
|
||||
за канал мінімізовані, але діаметр мережі впливає на кількість необхідних
|
||||
ітерацій для повного впорядкування даних.
|
||||
// T_dt=t_n+(m*t_k)*l
|
||||
// t_n - latency
|
||||
// t_k - throughput
|
||||
// m - message size (bytes)
|
||||
// l - hops (length)
|
||||
|
||||
Нижче наведено код програми, що реалізує паралельне сортування. Програма
|
||||
автоматично визначає кількість процесів та розподіляє масив.
|
||||
|
||||
#{
|
||||
set par(first-line-indent: 0pt)
|
||||
raw(read("main.c"), block: true)
|
||||
}
|
||||
|
||||
Нижче наведено результати запуску програми для різної кількості процесів ($p=1,2,4$).
|
||||
|
||||
#figure(image("proc1.png"), caption: [Результат виконання програми для одного процесу])
|
||||
#figure(image("proc2.png"), caption: [Результат виконання програми для двох процесів])
|
||||
#figure(image("proc4.png"), caption: [Результат виконання програми для чотирьох процесів])
|
||||
|
||||
Для масиву розміром $N=25000$:
|
||||
|
||||
#table(
|
||||
columns: (1fr, 1fr, 1fr, 1fr),
|
||||
align: center,
|
||||
[К-сть процесів], [Час (с)], [Прискорення $S_p$], [Ефективність $E_p$],
|
||||
[1], [0.00601], [1.0], [100%],
|
||||
[2], [0.00607], [0.99], [0.495],
|
||||
[4], [0.00321], [1.87], [0.5],
|
||||
)
|
||||
|
||||
== Висновки
|
||||
#v(-spacing)
|
||||
У ході лабораторної роботи було розроблено програмний засіб мовою C з
|
||||
використанням бібліотеки MPI для сортування масиву методом парного-непарного
|
||||
обміну (Odd-Even Sort), що відповідає кільцевій топології.
|
||||
|
||||
За результатами експериментів для розмірності завдання $N=25000$ було встановлено наступне:
|
||||
|
||||
За результатами експериментів для розмірності завдання $N=25 000$ було отримано наступні показники:
|
||||
|
||||
+ послідовне виконання ($p=1$): Час виконання склав $0.006011$ с. Це є базовим
|
||||
показником для розрахунку прискорення;
|
||||
+ виконання на 2 процесах ($p=2$): Час склав $0.006070$ с. Спостерігається
|
||||
незначне уповільнення ($S_2 approx 0.99$). Це свідчить про те, що для двох
|
||||
процесів виграш від розподілу обчислень (сортування двох підмасивів по 12 500
|
||||
елементів) був повністю нівельований накладними витратами на ініціалізацію MPI
|
||||
та передачу даних між процесами;
|
||||
+ виконання на 4 процесах ($p=4$): Час склав $0.003211$ с. Отримано прискорення
|
||||
$S_4 = 0.00601 / 0.003211 approx 1.87$. Ефективність становить $E_4 approx 46.8%$.
|
||||
|
||||
На відміну від запуску на 2 процесах, при розбитті задачі на 4 частини
|
||||
(по 6 250 елементів на процес) зменшення часу локального сортування (яке має
|
||||
складність $O(N log N)$) виявилося достатньо суттєвим, щоб перекрити
|
||||
комунікаційні витрати. Це дозволило отримати майже двократний приріст швидкодії
|
||||
порівняно з послідовною версією навіть на відносно малому масиві даних.
|
||||
|
||||
Таким чином, експеримент підтвердив, що ефективність MPI-програми залежить не
|
||||
тільки від розміру даних, але й від балансу між обчислювальною складністю
|
||||
локальної задачі та інтенсивністю обмінів.
|
||||
17
lab4/doc.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
subject: ТВО
|
||||
doctype: ЛБ
|
||||
mentors:
|
||||
- name: Міщеряков Ю. В.
|
||||
degree: Професор кафедри СТ
|
||||
gender: m
|
||||
edu_program: &EDU КНТ
|
||||
university: ХНУРЕ
|
||||
authors:
|
||||
- name: Орлов О. С.
|
||||
# full_name_gen: Косач Лариси Петрівни
|
||||
course: 4
|
||||
edu: *EDU
|
||||
gender: m
|
||||
group: 22-1
|
||||
semester: 7
|
||||
variant: 9
|
||||
97
lab4/main.c
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <math.h>
|
||||
#include <omp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef N
|
||||
#define N 10
|
||||
#endif
|
||||
|
||||
void initialize_matrix(double **matrix) {
|
||||
for (int i = 0; i < N; i++) {
|
||||
for (int j = 0; j < 2 * N; j++) {
|
||||
if (j < N) {
|
||||
matrix[i][j] = (rand() % 100) + 1;
|
||||
} else {
|
||||
matrix[i][j] = (j == (i + N)) ? 1.0 : 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_OUT
|
||||
void print_matrix(double **matrix) {
|
||||
for (int i = 0; i < N; i++) {
|
||||
for (int j = 0; j < 2 * N; j++) {
|
||||
printf("%6.2f ", matrix[i][j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
srand(time(NULL));
|
||||
|
||||
double **matrix = (double **)malloc(N * sizeof(double *));
|
||||
for (int i = 0; i < N; i++) {
|
||||
matrix[i] = (double *)malloc(2 * N * sizeof(double));
|
||||
}
|
||||
|
||||
initialize_matrix(matrix);
|
||||
|
||||
printf("Matrix size: %dx%d\n", N, N);
|
||||
#ifdef DEBUG_OUT
|
||||
print_matrix(matrix);
|
||||
#endif
|
||||
|
||||
double start_time = omp_get_wtime();
|
||||
|
||||
#pragma omp parallel
|
||||
for (int i = 0; i < N; i++) {
|
||||
#pragma omp master
|
||||
{
|
||||
double pivot = matrix[i][i];
|
||||
|
||||
if (fabs(pivot) < 1e-7) {
|
||||
puts("Matrix is singular, cannot find inverted, exiting.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (int j = 0; j < 2 * N; j++) {
|
||||
matrix[i][j] /= pivot;
|
||||
}
|
||||
}
|
||||
|
||||
// #pragma omp parallel for
|
||||
#pragma omp for schedule(static)
|
||||
for (int k = 0; k < N; k++) {
|
||||
if (k != i) {
|
||||
double factor = matrix[k][i];
|
||||
for (int j = 0; j < 2 * N; j++) {
|
||||
matrix[k][j] -= factor * matrix[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double end_time = omp_get_wtime();
|
||||
double time_taken = end_time - start_time;
|
||||
#ifdef DEBUG_OUT
|
||||
printf("\n");
|
||||
print_matrix(matrix);
|
||||
#endif
|
||||
|
||||
int threads = omp_get_max_threads();
|
||||
|
||||
printf("Threads: %d\n", threads);
|
||||
printf("Time taken: %f seconds\n", time_taken);
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
free(matrix[i]);
|
||||
}
|
||||
free(matrix);
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
lab4/proc1.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
lab4/proc16.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
lab4/proc2.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
lab4/proc4.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
lab4/proc8.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
3956
lab4/ТВО_КНТ_22_1_Орлов_ЛБ4.pdf
Normal file
85
lab4/ТВО_КНТ_22_1_Орлов_ЛБ4.typ
Normal file
@@ -0,0 +1,85 @@
|
||||
#import "@local/nure:0.1.0": *
|
||||
|
||||
#show: pz-lb.with(
|
||||
..yaml("doc.yaml"),
|
||||
worknumber: 4,
|
||||
title: "ПАРАЛЕЛЬНЕ ПРОГРАМУВАННЯ З ВИКОРИСТАННЯМ ТЕХНОЛОГІЇ OPENMP",
|
||||
)
|
||||
|
||||
== Мета роботи
|
||||
#v(-spacing)
|
||||
Ознайомлення з принципами роботи паралельних програм із використанням
|
||||
технології OpenMP, засобами їх розробки і запуску.
|
||||
|
||||
== Хід роботи
|
||||
#v(-spacing)
|
||||
|
||||
Згідно з варіантом №9, необхідно розробити програму для знаходження оберненої
|
||||
матриці методом Гаусса. Алгоритм був розпаралелений за допомогою директиви
|
||||
`#pragma omp parallel for`, яка розподіляє ітерації циклу між потоками.
|
||||
|
||||
Нижче наведено код розробленої програми мовою C:
|
||||
#{
|
||||
set par(first-line-indent: 0pt)
|
||||
raw(read("main.c"), block: true)
|
||||
}
|
||||
|
||||
== Результати роботи
|
||||
#v(-spacing)
|
||||
|
||||
Проведено серію запусків програми зі змінною кількістю потоків (1, 2, 4, 8, 16)
|
||||
для матриці розмірністю $1000 times 1000$.
|
||||
|
||||
#figure(image("proc1.png"), caption: [Виконання для одного потоку])
|
||||
#figure(image("proc2.png"), caption: [Виконання для двох потоків])
|
||||
#figure(image("proc4.png"), caption: [Виконання для чотирьох потоків])
|
||||
#figure(image("proc8.png"), caption: [Виконання для вісьмох потоків])
|
||||
#figure(image("proc16.png"), caption: [Виконання для шістнадцяти потоків])
|
||||
|
||||
Результати вимірювань часу виконання та розрахунок прискорення занесено у таблицю:
|
||||
|
||||
#figure(
|
||||
table(
|
||||
columns: (auto, auto, auto, auto),
|
||||
align: center,
|
||||
[Кількість потоків], [Час виконання (с)], [Прискорення ($S$)], [Ефективність ($E$)],
|
||||
[1], [$8.83$], [1.00], [100%],
|
||||
[2],
|
||||
[$5.02$],
|
||||
[$#{ calc.round(decimal("8.83") / decimal("5.02"), digits: 2) }$],
|
||||
[$#{ calc.round(calc.round(decimal("8.83") / decimal("5.02"), digits: 2) / 2 * 100) }%$],
|
||||
|
||||
[4],
|
||||
[$2.62$],
|
||||
[$#{ calc.round(decimal("8.83") / decimal("2.62"), digits: 2) }$],
|
||||
[$#{ calc.round(calc.round(decimal("8.83") / decimal("2.62"), digits: 2) / 4 * 100) }%$],
|
||||
|
||||
[8],
|
||||
[$1.63$],
|
||||
[$#{ calc.round(decimal("8.83") / decimal("1.63"), digits: 2) }$],
|
||||
[$#{ calc.round(calc.round(decimal("8.83") / decimal("1.63"), digits: 2) / 8 * 100) }%$],
|
||||
|
||||
[16],
|
||||
[$3.28$],
|
||||
[$#{ calc.round(decimal("8.83") / decimal("3.28"), digits: 2) }$],
|
||||
[$#{ calc.round(calc.round(decimal("8.83") / decimal("3.28"), digits: 2) / 16 * 100) }%$],
|
||||
),
|
||||
caption: [Показники ефективності паралельного алгоритму],
|
||||
)
|
||||
|
||||
== Аналіз результатів
|
||||
#v(-spacing)
|
||||
|
||||
Найбільше прискорення спостерігається при переході з 4 на 8 потоків,
|
||||
що зумовлено наявністю в комп'ютері восьми логічних потоків (чотирьох фізичних ядер).
|
||||
При переході на 16 потоків, час стрімко падає через постійний context switching.
|
||||
|
||||
== Висновки
|
||||
#v(-spacing)
|
||||
|
||||
У ході лабораторної роботи було вивчено технологію OpenMP та принципи розробки
|
||||
багатопотокових додатків для систем зі спільною пам'яттю. Реалізовано
|
||||
паралельний алгоритм знаходження оберненої матриці методом Гаусса. Практичні
|
||||
результати показали, що використання OpenMP дозволяє суттєво зменшити час
|
||||
виконання обчислювально складних задач. Однак, прискорення не є лінійним через
|
||||
накладні витрати на керування потоками та доступ до пам'яті.
|
||||
BIN
pz1/diag1_full.png
Normal file
|
After Width: | Height: | Size: 147 KiB |
3
pz1/diag1_full.svg
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
pz1/diag1_full.webp
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
pz1/diag2_full.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
pz1/diag3_full.png
Normal file
|
After Width: | Height: | Size: 205 KiB |