#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void matrix_vector_multiply(double *A, double *b, double *c, int start_row, int end_row, int M) {
for (int i = start_row; i < end_row; i++) {
c[i] = 0;
for (int j = 0; j < M; j++) {
c[i] += A[i * M + j] * b[j];
}
}
}
int parse_integer(const char *str) {
int value = 0;
while (*str) {
if (*str < '0' || *str > '9') {
return -1; // Invalid input
}
value = value * 10 + (*str - '0');
str++;
}
return value;
}
int main(int argc, char **argv) {
int rank, size, N, M;
// Initialize MPI
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Check command-line arguments for matrix dimensions
if (argc != 3) {
if (rank == 0) {
printf("Usage: %s <num_rows> <num_columns>\n", argv
[0]); }
MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
}
// Parse matrix dimensions
N = parse_integer(argv[1]);
M = parse_integer(argv[2]);
if (N <= 0 || M <= 0) {
if (rank == 0) {
printf("Invalid matrix dimensions: %s x %s\n", argv
[1], argv
[2]); }
MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
}
double *A = NULL;
double *b = NULL;
double *c
= (double *)malloc(N
* sizeof(double));
// Master process initializes the matrix and vector
if (rank == 0) {
A
= (double *)malloc(N
* M
* sizeof(double)); b
= (double *)malloc(M
* sizeof(double));
// Initialize matrix A and vector b with simple values
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
A[i * M + j] = 1.0; // Example initialization
for (int j = 0; j < M; j++)
b[j] = 1.0; // Example initialization
}
// Broadcast vector b to all processes
MPI_Bcast(b, M, MPI_DOUBLE, 0, MPI_COMM_WORLD);
// Each process computes its assigned rows
int rows_per_process = N / size;
int start_row = rank * rows_per_process;
int end_row = (rank == size - 1) ? N : start_row + rows_per_process;
double *local_c
= (double *)malloc((end_row
- start_row
) * sizeof(double)); matrix_vector_multiply(A, b, local_c, start_row, end_row, M);
// Gather results in the master process
MPI_Gather(local_c, end_row - start_row, MPI_DOUBLE, c, end_row - start_row, MPI_DOUBLE, 0, MPI_COMM_WORLD);
// Master process prints the result
if (rank == 0) {
for (int i = 0; i < N; i++) {
printf("c[%d] = %f\n", i
, c
[i
]); }
}
MPI_Finalize();
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPG1waS5oPgoKdm9pZCBtYXRyaXhfdmVjdG9yX211bHRpcGx5KGRvdWJsZSAqQSwgZG91YmxlICpiLCBkb3VibGUgKmMsIGludCBzdGFydF9yb3csIGludCBlbmRfcm93LCBpbnQgTSkgewogICAgZm9yIChpbnQgaSA9IHN0YXJ0X3JvdzsgaSA8IGVuZF9yb3c7IGkrKykgewogICAgICAgIGNbaV0gPSAwOwogICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgTTsgaisrKSB7CiAgICAgICAgICAgIGNbaV0gKz0gQVtpICogTSArIGpdICogYltqXTsKICAgICAgICB9CiAgICB9Cn0KCmludCBwYXJzZV9pbnRlZ2VyKGNvbnN0IGNoYXIgKnN0cikgewogICAgaW50IHZhbHVlID0gMDsKICAgIHdoaWxlICgqc3RyKSB7CiAgICAgICAgaWYgKCpzdHIgPCAnMCcgfHwgKnN0ciA+ICc5JykgewogICAgICAgICAgICByZXR1cm4gLTE7IC8vIEludmFsaWQgaW5wdXQKICAgICAgICB9CiAgICAgICAgdmFsdWUgPSB2YWx1ZSAqIDEwICsgKCpzdHIgLSAnMCcpOwogICAgICAgIHN0cisrOwogICAgfQogICAgcmV0dXJuIHZhbHVlOwp9CgppbnQgbWFpbihpbnQgYXJnYywgY2hhciAqKmFyZ3YpIHsKICAgIGludCByYW5rLCBzaXplLCBOLCBNOwoKICAgIC8vIEluaXRpYWxpemUgTVBJCiAgICBNUElfSW5pdCgmYXJnYywgJmFyZ3YpOwogICAgTVBJX0NvbW1fcmFuayhNUElfQ09NTV9XT1JMRCwgJnJhbmspOwogICAgTVBJX0NvbW1fc2l6ZShNUElfQ09NTV9XT1JMRCwgJnNpemUpOwoKICAgIC8vIENoZWNrIGNvbW1hbmQtbGluZSBhcmd1bWVudHMgZm9yIG1hdHJpeCBkaW1lbnNpb25zCiAgICBpZiAoYXJnYyAhPSAzKSB7CiAgICAgICAgaWYgKHJhbmsgPT0gMCkgewogICAgICAgICAgICBwcmludGYoIlVzYWdlOiAlcyA8bnVtX3Jvd3M+IDxudW1fY29sdW1ucz5cbiIsIGFyZ3ZbMF0pOwogICAgICAgIH0KICAgICAgICBNUElfQWJvcnQoTVBJX0NPTU1fV09STEQsIEVYSVRfRkFJTFVSRSk7CiAgICB9CgoKICAgIC8vIFBhcnNlIG1hdHJpeCBkaW1lbnNpb25zCiAgICBOID0gcGFyc2VfaW50ZWdlcihhcmd2WzFdKTsKICAgIAogICAgTSA9IHBhcnNlX2ludGVnZXIoYXJndlsyXSk7CgogICAgaWYgKE4gPD0gMCB8fCBNIDw9IDApIHsKICAgICAgICBpZiAocmFuayA9PSAwKSB7CiAgICAgICAgICAgIHByaW50ZigiSW52YWxpZCBtYXRyaXggZGltZW5zaW9uczogJXMgeCAlc1xuIiwgYXJndlsxXSwgYXJndlsyXSk7CiAgICAgICAgfQogICAgICAgIE1QSV9BYm9ydChNUElfQ09NTV9XT1JMRCwgRVhJVF9GQUlMVVJFKTsKICAgIH0KCiAgICBkb3VibGUgKkEgPSBOVUxMOwogICAgZG91YmxlICpiID0gTlVMTDsKICAgIGRvdWJsZSAqYyA9IChkb3VibGUgKiltYWxsb2MoTiAqIHNpemVvZihkb3VibGUpKTsKCiAgICAvLyBNYXN0ZXIgcHJvY2VzcyBpbml0aWFsaXplcyB0aGUgbWF0cml4IGFuZCB2ZWN0b3IKICAgIGlmIChyYW5rID09IDApIHsKICAgICAgICBBID0gKGRvdWJsZSAqKW1hbGxvYyhOICogTSAqIHNpemVvZihkb3VibGUpKTsKICAgICAgICBiID0gKGRvdWJsZSAqKW1hbGxvYyhNICogc2l6ZW9mKGRvdWJsZSkpOwoKICAgICAgICAvLyBJbml0aWFsaXplIG1hdHJpeCBBIGFuZCB2ZWN0b3IgYiB3aXRoIHNpbXBsZSB2YWx1ZXMKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IE47IGkrKykKICAgICAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBNOyBqKyspCiAgICAgICAgICAgICAgICBBW2kgKiBNICsgal0gPSAxLjA7ICAvLyBFeGFtcGxlIGluaXRpYWxpemF0aW9uCiAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCBNOyBqKyspCiAgICAgICAgICAgIGJbal0gPSAxLjA7ICAvLyBFeGFtcGxlIGluaXRpYWxpemF0aW9uCiAgICB9CgogICAgLy8gQnJvYWRjYXN0IHZlY3RvciBiIHRvIGFsbCBwcm9jZXNzZXMKICAgIE1QSV9CY2FzdChiLCBNLCBNUElfRE9VQkxFLCAwLCBNUElfQ09NTV9XT1JMRCk7CgogICAgLy8gRWFjaCBwcm9jZXNzIGNvbXB1dGVzIGl0cyBhc3NpZ25lZCByb3dzCiAgICBpbnQgcm93c19wZXJfcHJvY2VzcyA9IE4gLyBzaXplOwogICAgaW50IHN0YXJ0X3JvdyA9IHJhbmsgKiByb3dzX3Blcl9wcm9jZXNzOwogICAgaW50IGVuZF9yb3cgPSAocmFuayA9PSBzaXplIC0gMSkgPyBOIDogc3RhcnRfcm93ICsgcm93c19wZXJfcHJvY2VzczsKCiAgICBkb3VibGUgKmxvY2FsX2MgPSAoZG91YmxlICopbWFsbG9jKChlbmRfcm93IC0gc3RhcnRfcm93KSAqIHNpemVvZihkb3VibGUpKTsKICAgIG1hdHJpeF92ZWN0b3JfbXVsdGlwbHkoQSwgYiwgbG9jYWxfYywgc3RhcnRfcm93LCBlbmRfcm93LCBNKTsKCiAgICAvLyBHYXRoZXIgcmVzdWx0cyBpbiB0aGUgbWFzdGVyIHByb2Nlc3MKICAgIE1QSV9HYXRoZXIobG9jYWxfYywgZW5kX3JvdyAtIHN0YXJ0X3JvdywgTVBJX0RPVUJMRSwgYywgZW5kX3JvdyAtIHN0YXJ0X3JvdywgTVBJX0RPVUJMRSwgMCwgTVBJX0NPTU1fV09STEQpOwoKICAgIC8vIE1hc3RlciBwcm9jZXNzIHByaW50cyB0aGUgcmVzdWx0CiAgICBpZiAocmFuayA9PSAwKSB7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBOOyBpKyspIHsKICAgICAgICAgICAgcHJpbnRmKCJjWyVkXSA9ICVmXG4iLCBpLCBjW2ldKTsKICAgICAgICB9CiAgICAgICAgZnJlZShBKTsKICAgICAgICBmcmVlKGIpOwogICAgfQoKICAgIGZyZWUobG9jYWxfYyk7CiAgICBmcmVlKGMpOwogICAgTVBJX0ZpbmFsaXplKCk7CiAgICByZXR1cm4gMDsKCiAgICAKfQoK