#include <stdio.h>
#include <stdlib.h>
#include < mpi.h>
int main(int argc, char **argv)
{
int rank, size, i, j, n,
// Initialize MPI
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Take input for n
if (rank == 0)
{
printf("Enter the value of n (must be divisible by p): ");
scanf_s("%d", &n);
}
// Broadcast n to all processes
MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
// Take input for p
if (rank == 0)
{
printf("Enter the value of p (must be smaller than n): ");
scanf_s("%d", &p);
}
// Broadcast p to all processes
MPI_Bcast(&p, 1, MPI_INT, 0, MPI_COMM_WORLD);
// Error handling for p and n
if (n % p != 0)
{
if (rank == 0)
printf("Error: n must be divisible by p.\n");
MPI_Finalize();
return 0;
}
if (p >= n)
{
if (rank == 0)
printf("Error: p must be smaller than n.\n");
MPI_Finalize();
return 0;
}
// Define matrices and vectors dynamically
int *A = (int *)malloc(sizeof(int) * n * n);
int *x = (int *)malloc(sizeof(int) * n);
int *y = (int *)malloc(sizeof(int) * n);
int *local_A = (int *)malloc(sizeof(int) * (n / p) * n);
int *local_x = (int *)malloc(sizeof(int) * (n / p));
int *local_y = (int *)malloc(sizeof(int) * (n / p));
// Initialize matrices and vectors with random values
if (rank == 0)
{
printf("\nMatrix A:\n");
for (i = 0; i < n * n; i++)
{
A[i] = rand() % 101; // random integer between 0 and 100
printf("%d\t", A[i]);
if ((i + 1) % n == 0)
printf("\n");
}
printf("\nVector x:\n");
for (i = 0; i < n; i++)
{
x[i] = rand() % 101; // random integer between 0 and 100
printf("%d\n", x[i]);
}
}
// Broadcast matrices and vectors to all processes
MPI_Bcast(A, n * n, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Bcast(x, n, MPI_INT, 0, MPI_COMM_WORLD);
// Calculate the local size for each process
int local_n = n / size;
// Scatter matrix A to all processes
MPI_Scatter(A, local_n * n, MPI_INT, local_A, local_n * n, MPI_INT, 0, MPI_COMM_WORLD);
// Scatter vector x to all processes
MPI_Scatter(x, local_n, MPI_INT, local_x, local_n, MPI_INT, 0, MPI_COMM_WORLD);
// Compute local vector elements
for (i = 0; i < local_n; i++)
{
local_y[i] = 0;
for (j = 0; j < n; j++)
{
local_y[i] += local_A[i * n + j] * local_x[j];
}
}
// Gather local results back to process 0
MPI_Gather(local_y, local_n, MPI_INT, y, local_n, MPI_INT, 0, MPI_COMM_WORLD);
// Process 0 prints the result
if (rank == 0)
{
printf("\nResultant Vector y:\n");
for (i = 0; i < n; i++)
{
printf("y[%d] = %d\n", i, y[i]);
}
}
// Free dynamically allocated memory
free(A);
free(x);
free(y);
free(local_A);
free(local_x);
free(local_y);
// Finalize MPI
MPI_Finalize();
return 0;
}