Листинг программы
Для матрицы 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;
}
