Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

парал прогр / 2020_2021_311_парал_Филатова_Work15

.docx
Скачиваний:
8
Добавлен:
18.08.2022
Размер:
30.97 Кб
Скачать

Work15 Филатова Ольга 311

Метод Зейделя

Номер теста

Порядок системы

Последовательный алгоритм

Параллельный алгоритм

Время

Ускорение

1

10

0.000014

0.000044

0,318182

2

100

0.000308

0.000264

1,166667

3

500

0.005785

0.003654

1,583196

4

1000

0.025000

0.019698

1,269164

5

1500

0.061652

0.051225

1,203553

6

2000

0.108430

0.085845

1,26309

7

2500

0.196513

0.147830

1,329317

8

3000

0.256172

0.177108

1,446417

Параллельный алгоритм работает на больших порядках быстрее. Чем больше размерность, тем больше ускорение

Номер теста

Порядок системы

Ускорение алгоритма Гаусса

Ускорение алгоритма Зейделя

1

10

0

0,318182

2

100

0,714286

1,166667

3

500

1,132006

1,583196

4

1000

1,394516

1,269164

5

1500

1,177705

1,203553

6

2000

1,542908

1,26309

7

2500

1,550632

1,329317

8

3000

1,524502

1,446417

Ускорение параллельного алгоритма Гаусса оказалось больше, но время, затрачиваемое на работу, тоже больше.

#include <stdio.h>

#include <stdlib.h>

#include <conio.h>

#include <time.h>

#include <math.h>

#include "mpi.h"

int ProcNum;

int ProcRank;

int* pProcInd;

int* pProcNum;

double* xk;

double* xk_1;

// Function for random initialization of the matrix and the vector elements

void RandomDataInitialization(double* pMatrix, double* pVector, int Size) {

int i, j;

srand(unsigned(clock()));

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

pVector[i] = rand() / double(1000);

for (j = 0; j < Size; j++) {

if (j <= i)

pMatrix[i * Size + j] = rand() / double(1000);

else

pMatrix[i * Size + j] = 0;

}

}

}

// Function for memory allocation and definition of the objects elements

void ProcessInitialization(double*& pMatrix, double*& pVector, double*& pResult, double*& pProcRows, double*& pProcVector, double*& pProcResult, int& Size, int& RowNum) {

if (ProcRank == 0) {

// Setting the size of the matrix and the vector

do {

printf("\nEnter size of the matrix and the vector: ");

scanf_s("%d", &Size);

printf("\nChosen size = %d \n", Size);

if (Size <= 0)

printf("\nSize of objects must be greater than 0!\n");

} while (Size <= 0);

}

MPI_Bcast(&Size, 1, MPI_INT, 0, MPI_COMM_WORLD);

pProcRows = new double[Size * Size];

pProcVector = new double[Size];

pProcResult = new double[Size];

pProcInd = new int[Size];

pProcNum = new int[Size];

// Memory allocation

if (ProcRank == 0) {

pMatrix = new double[Size * Size];

pVector = new double[Size];

pResult = new double[Size];

xk = new double[Size];

xk_1 = new double[Size];

// Initialization of the matrix and the vector elements

RandomDataInitialization(pMatrix, pVector, Size);

}

}

// Function for data distribution

void DataDistribution(double* pMatrix, double* pProcRows, double* pVector, double* pProcVector, int Size, int RowNum) {

int* pSendNum;

int* pSendInd;

int i;

pSendInd = new int[ProcNum];

pSendNum = new int[ProcNum];

RowNum = Size;

pSendNum[0] = RowNum * Size;

pSendInd[0] = 0;

for (i = 1; i < ProcNum; i++) {

pSendNum[i] = RowNum * Size;

pSendInd[i] = 0;

}

MPI_Scatterv(pMatrix, pSendNum, pSendInd, MPI_DOUBLE, pProcRows, RowNum * Size, MPI_DOUBLE, 0, MPI_COMM_WORLD);

pProcInd[0] = 0;

pProcNum[0] = Size;

for (i = 1; i < ProcNum; i++) {

pProcInd[i] = 0;

pProcNum[i] = Size;

}

MPI_Scatterv(pVector, pProcNum, pProcInd, MPI_DOUBLE, pProcVector, pProcNum[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD);

delete[] pSendNum;

delete[] pSendInd;

}

// Function for formatted vector output

void PrintVector(double* pVector, int Size) {

int i;

for (i = 0; i < Size; i++)

printf("%7.4f ", pVector[i]);

}

// Function for computational process termination

void ProcessTermination(double* pMatrix, double* pVector, double* pResult, double* pProcRows, double* pProcVector, double* pProcResult) {

if (ProcRank == 0) {

delete[] pMatrix;

delete[] pVector;

delete[] pResult;

}

delete[] pProcRows;

delete[] pProcVector;

delete[] pProcResult;

}

// Normal system

double Normal(double* x1, double* x2, int Size) {

double norm = fabs(x1[0] - x2[0]);

for (int i = 1; i < Size; i += 1) {

if (fabs(x1[i] - x2[i]) > norm) {

norm = fabs(x1[i] - x2[i]);

}

}

return norm;

}

// Function for the execution of Zeidel algorithm

void ZeidelCalculation(double* pMatrix, double* pVector, double* pResult, int Size) {

if (ProcRank == 0) {

for (int i = 0; i < Size; i++) {

xk[i] = 0.0;

xk_1[i] = 0.0;

}

}

double* xkProc = new double[Size];

double* xk_plus_1Proc = new double[Size];

pProcInd[0] = 0;

pProcNum[0] = Size;

for (int i = 1; i < ProcNum; i++) {

pProcInd[i] = 0;

pProcNum[i] = Size;

}

MPI_Scatterv(xk, pProcNum, pProcInd, MPI_DOUBLE, xkProc, pProcNum[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Scatterv(xk_1, pProcNum, pProcInd, MPI_DOUBLE, xk_plus_1Proc, pProcNum[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD);

bool stop = false;

while (!stop) {

double sum1, sum2, s1, s2;

for (int i = 0; i < Size; i++) {

sum1 = 0.0;

for (int j = ProcRank; j <= i - 1; j += ProcNum) {

sum1 += xk_plus_1Proc[j] * pMatrix[i * Size + j];

}

MPI_Reduce(&sum1, &s1, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

sum2 = 0.0;

for (int j = ProcRank + i + 1; j < Size; j += ProcNum) {

sum2 += xkProc[j] * pMatrix[i * Size + j];

}

MPI_Reduce(&sum2, &s2, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

if (ProcRank == 0)

xk_1[i] = (pVector[i] - s1 - s2) / pMatrix[i * Size + i];

MPI_Scatterv(xk, pProcNum, pProcInd, MPI_DOUBLE, xkProc,

pProcNum[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Scatterv(xk_1, pProcNum, pProcInd, MPI_DOUBLE, xk_plus_1Proc,

pProcNum[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD);

}

if (ProcRank == 0) {

if (Normal(xk, xk_1, Size) < 0.0001) {

stop = true;

}

else {

for (int i = 0; i < Size; i++) {

xk[i] = xk_1[i];

}

}

}

}

if (ProcRank == 0) {

for (int i = 0; i < Size; i++) {

pResult[i] = xk_1[i];

}

}

}

int main() {

double* pMatrix; // The matrix of the linear system

double* pVector; // The right parts of the linear system

double* pResult; // The result vector

double* pProcRows;

double* pProcVector;

double* pProcResult;

int Size; // The size of the matrix and the vectors

int RowNum;

double start, finish, duration;

setvbuf(stdout, NULL, _IONBF, 0);

MPI_Init(NULL, NULL);

MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);

MPI_Comm_size(MPI_COMM_WORLD, &ProcNum);

if (ProcRank == 0) {

printf("Zeidel algorithm for solving linear systems\n");

}

// Data initialization

ProcessInitialization(pMatrix, pVector, pResult, pProcRows, pProcVector, pProcResult, Size, RowNum);

DataDistribution(pMatrix, pProcRows, pVector, pProcVector, Size, RowNum);

start = MPI_Wtime();

ZeidelCalculation(pProcRows, pProcVector, pResult, Size);

finish = MPI_Wtime();

duration = finish - start;

if (ProcRank == 0)

printf("\n Time of execution: %f\n", duration); // Printing the time spent by parallel Zeidel algorithm

ProcessTermination(pMatrix, pVector, pResult, pProcRows, pProcVector, pProcResult); // Program termination

MPI_Finalize();

}