Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПРО-429_ЛР4_ПВ.docx
Скачиваний:
1
Добавлен:
07.04.2025
Размер:
470 Кб
Скачать
☆

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

Для матрицы NxL:

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#include <mpi.h>

void fillMatrix(double* matrix, int rows, int cols) {

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

for (int j = 0; j < cols; ++j) {

matrix[i * cols + j] = (double)rand() / RAND_MAX;

}

}

}

void printMatrix(double* matrix, int rows, int cols) {

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

for (int j = 0; j < cols; ++j) {

printf("%.2f ", matrix[i * cols + j]);

}

printf("\n");

}

}

void matrixVectorMultiply(double* matrix, double* vector, double* result, int size) {

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

result[i] = 0.0;

for (int j = 0; j < size; ++j) {

result[i] += matrix[i * size + j] * vector[j];

}

}

}

int main(int argc, char** argv) {

MPI_Init(&argc, &argv);

int rank, size;

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Comm_size(MPI_COMM_WORLD, &size);

double time = 0, start_time, end_time;

long int N = 5000;

//if (rank == 0) {

// printf("Enter the value of N: ");

// scanf("%d", &N);

//}

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

int localN = N / size;

int localSize = (rank == size - 1) ? N - (size - 1) * localN : localN;

double* A = (double*)malloc(N * N * sizeof(double));

double* B = (double*)malloc(N * sizeof(double));

double* C = (double*)malloc(N * sizeof(double));

double* D = (double*)malloc(N * sizeof(double));

if (rank == 0) {

fillMatrix(A, N, N);

fillMatrix(B, 1, N);

fillMatrix(C, 1, N);

fillMatrix(D, 1, N);

}

double* localA = (double*)malloc(localSize * N * sizeof(double));

double* localB = (double*)malloc(N * sizeof(double));

double* localC = (double*)malloc(N * sizeof(double));

double* localD = (double*)malloc(N * sizeof(double));

double* localResult = (double*)malloc(localSize * sizeof(double));

start_time = MPI_Wtime();

MPI_Scatter(A, localSize * N, MPI_DOUBLE, localA, localSize * N, MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Scatter(B, localN, MPI_DOUBLE, localB, localN, MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Scatter(C, localN, MPI_DOUBLE, localC, localN, MPI_DOUBLE, 0, MPI_COMM_WORLD);

MPI_Scatter(D, localN, MPI_DOUBLE, localD, localN, MPI_DOUBLE, 0, MPI_COMM_WORLD);

end_time = MPI_Wtime();

time += end_time - start_time;

//printf("Rank %d: Scatter Time = %.6f seconds\n", rank, end_time - start_time);

start_time = MPI_Wtime();

matrixVectorMultiply(localA, localB, localResult, localSize);

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

localResult[i] += localC[i] * localD[i];

}

end_time = MPI_Wtime();

time += end_time - start_time;

//printf("Rank %d: Computation Time = %.6f seconds\n", rank, end_time - start_time);

double* result = (double*)malloc(N * sizeof(double));

start_time = MPI_Wtime();

MPI_Gather(localResult, localSize, MPI_DOUBLE, result, localSize, MPI_DOUBLE, 0, MPI_COMM_WORLD);

end_time = MPI_Wtime();

time += end_time - start_time;

//printf("Rank %d: Gather Time = %.6f seconds\n", rank, end_time - start_time);

printf("\nRank %d: Time = %.6f seconds\n", rank, time);

if (rank == 0) {

printf("Result vector:\n");

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

printf("%.2f ", result[i]);

}

printf("\n");

}

free(A);

free(B);

free(C);

free(D);

free(localA);

free(localB);

free(localC);

free(localD);

free(localResult);

free(result);

MPI_Finalize();

return 0;

}

Для матрицы LxL:

#include <mpi.h>

#include <iostream>

#include <fstream>

#include <thread>

#include <ctime>

using namespace std;

#define FILL_CHAR 219

#define EMPTY_CHAR 255

unsigned int inline get(int* array, int* left, int* right, int size, int chunk, int y, int x) {

if (y < 0) y = size -1;

if (y >= size) y = 0;

if (x < 0) return left[(y)];

if (x >= chunk) return right[(y)];

return array[(x) * size + (y)];

}

int process(int* array1, int* array2, int* left, int* right, int size, int chunk) {

int i, j;

int count_alive = 0;

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

{

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

int alive_near = get(array1, left, right, size,chunk, j-1, i-1) +

get(array1, left, right, size, chunk, j-1, i ) +

get(array1, left, right, size, chunk, j-1, i + 1) +

get(array1, left, right, size, chunk, j , i-1) +

get(array1, left, right, size, chunk, j , i + 1) +

get(array1, left, right, size, chunk, j + 1, i -1) +

get(array1, left, right, size, chunk, j + 1, i + 1) +

get(array1, left, right, size, chunk, j + 1, i);

if (alive_near > 3)

{

array2[i * size + j] = 0;

}

else if (alive_near > 2)

{

array2[i * size + j] = 1;

count_alive++;

}

else if (alive_near > 1)

{

array2[i * size + j] = array1[i * size + j];

count_alive += array1[i * size + j] ? 1 : 0;

}

else {

array2[i * size + j] = 0;

}

}

}

return count_alive;

}

#pragma comment(linker, "/STACK:1024000000")

int main(int argc, char* argv[]){

int sizec, rank;

MPI_Status status;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &sizec);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

int size = 100;

int max_iterations =5000;

bool output = false;

int count_alive = 0;

int* array1 = new int[size * size];

int* array2 = new int[size * size];

int chunk = size / sizec; // количество столбцов на каждый процесс

int* array1_part = new int[size * chunk];

int* array2_part = new int[size * chunk];

int* left;

int* rigth;

left = new int[size];// теневые колонки каждого процесса

rigth = new int[size];

double start = 0;

double end = 0;

if (rank == 0) {

srand(time(NULL));

for ( int x = 0; x < size; x++)

{

for ( int y = 0; y < size; y++)

{

int r = rand() % 4 + 1;

array1[x * size + y] = r == 1 ? 1 : 0;

count_alive += r == 1 ? 1 : 0;

}

}

/*for (int i = 0; i < size; i++)

{

for (int j = 0; j < size; j++)

cout << array1[i * size + j] << " ";

cout << endl;

}

*/

start = MPI_Wtime();

}

MPI_Scatter(array1, chunk * size, MPI_INT, array1_part, chunk * size, MPI_INT, 0, MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);

int* cnt = new int[max_iterations];

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

int next = rank + 1;

int prev = rank - 1;

if (rank == 0) prev = sizec - 1;

if (rank == (sizec - 1)) next = 0;

MPI_Sendrecv(array1_part + size* (chunk -1 ), size, MPI_INT, next, 2, left, size, MPI_INT, prev, 2, MPI_COMM_WORLD, &status);

MPI_Sendrecv(array1_part, size, MPI_INT, prev, 3, rigth, size, MPI_INT, next, 3, MPI_COMM_WORLD, &status);

//мутируем

cnt[i] = process(array1_part, array2_part, left, rigth, size, chunk);

int* temp = array1_part;

array1_part = array2_part;

array2_part = temp;

}

MPI_Gather(array1_part, chunk * size, MPI_C_BOOL, array2, chunk * size, MPI_C_BOOL, 0, MPI_COMM_WORLD);

int* all = new int[max_iterations];

MPI_Reduce(cnt, all, max_iterations, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);

if (rank == 0) {

std::ofstream out;

out.open("out.txt");

if (out.is_open())

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

out << all[i] << endl;

out.close();

end = MPI_Wtime();

std::cout << "\nMatrix C:\n";

cout << "time: " << end - start << endl;

//<< all[0] << " " << all[0 * size + size] << "\n" << all[size * size + 0] << "\t" << all[max_iterations-1];

}

delete[] left;

delete[] rigth;

delete[] array1;

delete[] array1_part;

delete[] array2;

delete[] all;

delete[] cnt;

MPI_Finalize();

return 0;

}

Соседние файлы в предмете Параллельные вычисления