#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#define ARRAY_SIZE 1000008 // Define the maximum array size statically
void prefix_sum(int* local_data, int local_size, int* result) {
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Compute local prefix sum
result[0] = local_data[0];
for (int i = 1; i < local_size; i++) {
result[i] = result[i - 1] + local_data[i];
}
// Compute offset from previous ranks
int offset = 0;
if (rank != 0) {
int previous_sum;
MPI_Recv(&previous_sum, 1, MPI_INT, rank - 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
offset = previous_sum;
// Adjust the last element of the local prefix sum with the received offset
result[local_size - 1] += offset;
// Send the total sum of the current process to the next process
int total_sum = result[local_size - 1];
if (rank != size - 1) {
MPI_Send(&total_sum, 1, MPI_INT, rank + 1, 0, MPI_COMM_WORLD);
}
// Adjust all local results based on the offset
for (int i = 0; i < local_size - 1; i++) {
result[i] += offset;
}
}
// Send the total sum to the next rank
int total_sum = result[local_size - 1];
if (rank == 0) {
MPI_Send(&total_sum, 1, MPI_INT, rank + 1, 0, MPI_COMM_WORLD);
}
}
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);
// Ensure ARRAY_SIZE is divisible by size
if (ARRAY_SIZE % size != 0) {
if (rank == 0) {
fprintf(stderr
, "Array size must be divisible by the number of processes.\n"); }
MPI_Finalize();
return EXIT_FAILURE;
}
int total_size = ARRAY_SIZE;
int data[ARRAY_SIZE]; // Static allocation for the entire array
if (rank == 0) {
// Initialize array with ones
for (int i = 0; i < total_size; i++) {
data[i] = 1;
}
}
// Compute local size for each process
int local_size = total_size / size;
int local_data[local_size]; // Static allocation for local data
// Distribute data among processes
MPI_Scatter(data, local_size, MPI_INT, local_data, local_size, MPI_INT, 0, MPI_COMM_WORLD);
// Measure computation time
double start_time = MPI_Wtime();
// Compute prefix sum locally and adjust with offsets
int local_result[local_size]; // Static allocation for local result
prefix_sum(local_data, local_size, local_result);
// Gather the results back
static int result[ARRAY_SIZE]; // Static allocation for the final result
MPI_Gather(local_result, local_size, MPI_INT, result, local_size, MPI_INT, 0, MPI_COMM_WORLD);
double end_time = MPI_Wtime();
// Print the result and computation time
if (rank == 0) {
printf("%d ", result
[1000007]); printf("Computation Time: %f seconds\n", end_time
- start_time
); }
MPI_Finalize();
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPG1waS5oPgoKI2RlZmluZSBBUlJBWV9TSVpFIDEwMDAwMDggLy8gRGVmaW5lIHRoZSBtYXhpbXVtIGFycmF5IHNpemUgc3RhdGljYWxseQoKdm9pZCBwcmVmaXhfc3VtKGludCogbG9jYWxfZGF0YSwgaW50IGxvY2FsX3NpemUsIGludCogcmVzdWx0KSB7CiAgICBpbnQgcmFuaywgc2l6ZTsKICAgIE1QSV9Db21tX3JhbmsoTVBJX0NPTU1fV09STEQsICZyYW5rKTsKICAgIE1QSV9Db21tX3NpemUoTVBJX0NPTU1fV09STEQsICZzaXplKTsKCiAgICAvLyBDb21wdXRlIGxvY2FsIHByZWZpeCBzdW0KICAgIHJlc3VsdFswXSA9IGxvY2FsX2RhdGFbMF07CiAgICBmb3IgKGludCBpID0gMTsgaSA8IGxvY2FsX3NpemU7IGkrKykgewogICAgICAgIHJlc3VsdFtpXSA9IHJlc3VsdFtpIC0gMV0gKyBsb2NhbF9kYXRhW2ldOwogICAgfQoKICAgIC8vIENvbXB1dGUgb2Zmc2V0IGZyb20gcHJldmlvdXMgcmFua3MKICAgIGludCBvZmZzZXQgPSAwOwogICAgaWYgKHJhbmsgIT0gMCkgewogICAgICAgIGludCBwcmV2aW91c19zdW07CiAgICAgICAgTVBJX1JlY3YoJnByZXZpb3VzX3N1bSwgMSwgTVBJX0lOVCwgcmFuayAtIDEsIDAsIE1QSV9DT01NX1dPUkxELCBNUElfU1RBVFVTX0lHTk9SRSk7CiAgICAgICAgb2Zmc2V0ID0gcHJldmlvdXNfc3VtOwogICAgICAgIC8vIEFkanVzdCB0aGUgbGFzdCBlbGVtZW50IG9mIHRoZSBsb2NhbCBwcmVmaXggc3VtIHdpdGggdGhlIHJlY2VpdmVkIG9mZnNldAogICAgICAgIHJlc3VsdFtsb2NhbF9zaXplIC0gMV0gKz0gb2Zmc2V0OwogICAgICAgIC8vIFNlbmQgdGhlIHRvdGFsIHN1bSBvZiB0aGUgY3VycmVudCBwcm9jZXNzIHRvIHRoZSBuZXh0IHByb2Nlc3MKICAgICAgICBpbnQgdG90YWxfc3VtID0gcmVzdWx0W2xvY2FsX3NpemUgLSAxXTsKICAgICAgICBpZiAocmFuayAhPSBzaXplIC0gMSkgewogICAgICAgICAgICBNUElfU2VuZCgmdG90YWxfc3VtLCAxLCBNUElfSU5ULCByYW5rICsgMSwgMCwgTVBJX0NPTU1fV09STEQpOwogICAgICAgIH0KICAgICAgICAvLyBBZGp1c3QgYWxsIGxvY2FsIHJlc3VsdHMgYmFzZWQgb24gdGhlIG9mZnNldAogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbG9jYWxfc2l6ZSAtIDE7IGkrKykgewogICAgICAgICAgICByZXN1bHRbaV0gKz0gb2Zmc2V0OwogICAgICAgIH0KICAgIH0KICAgIC8vIFNlbmQgdGhlIHRvdGFsIHN1bSB0byB0aGUgbmV4dCByYW5rCiAgICBpbnQgdG90YWxfc3VtID0gcmVzdWx0W2xvY2FsX3NpemUgLSAxXTsKICAgIGlmIChyYW5rID09IDApIHsKICAgICAgICBNUElfU2VuZCgmdG90YWxfc3VtLCAxLCBNUElfSU5ULCByYW5rICsgMSwgMCwgTVBJX0NPTU1fV09STEQpOwogICAgfQp9CgppbnQgbWFpbihpbnQgYXJnYywgY2hhcioqIGFyZ3YpIHsKICAgIE1QSV9Jbml0KCZhcmdjLCAmYXJndik7CgogICAgaW50IHJhbmssIHNpemU7CiAgICBNUElfQ29tbV9yYW5rKE1QSV9DT01NX1dPUkxELCAmcmFuayk7CiAgICBNUElfQ29tbV9zaXplKE1QSV9DT01NX1dPUkxELCAmc2l6ZSk7CgogICAgLy8gRW5zdXJlIEFSUkFZX1NJWkUgaXMgZGl2aXNpYmxlIGJ5IHNpemUKICAgIGlmIChBUlJBWV9TSVpFICUgc2l6ZSAhPSAwKSB7CiAgICAgICAgaWYgKHJhbmsgPT0gMCkgewogICAgICAgICAgICBmcHJpbnRmKHN0ZGVyciwgIkFycmF5IHNpemUgbXVzdCBiZSBkaXZpc2libGUgYnkgdGhlIG51bWJlciBvZiBwcm9jZXNzZXMuXG4iKTsKICAgICAgICB9CiAgICAgICAgTVBJX0ZpbmFsaXplKCk7CiAgICAgICAgcmV0dXJuIEVYSVRfRkFJTFVSRTsKICAgIH0KCiAgICBpbnQgdG90YWxfc2l6ZSA9IEFSUkFZX1NJWkU7CiAgICBpbnQgZGF0YVtBUlJBWV9TSVpFXTsgLy8gU3RhdGljIGFsbG9jYXRpb24gZm9yIHRoZSBlbnRpcmUgYXJyYXkKCiAgICBpZiAocmFuayA9PSAwKSB7CiAgICAgICAgLy8gSW5pdGlhbGl6ZSBhcnJheSB3aXRoIG9uZXMKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHRvdGFsX3NpemU7IGkrKykgewogICAgICAgICAgICBkYXRhW2ldID0gMTsKICAgICAgICB9CiAgICB9CgogICAgLy8gQ29tcHV0ZSBsb2NhbCBzaXplIGZvciBlYWNoIHByb2Nlc3MKICAgIGludCBsb2NhbF9zaXplID0gdG90YWxfc2l6ZSAvIHNpemU7CiAgICBpbnQgbG9jYWxfZGF0YVtsb2NhbF9zaXplXTsgLy8gU3RhdGljIGFsbG9jYXRpb24gZm9yIGxvY2FsIGRhdGEKCiAgICAvLyBEaXN0cmlidXRlIGRhdGEgYW1vbmcgcHJvY2Vzc2VzCiAgICBNUElfU2NhdHRlcihkYXRhLCBsb2NhbF9zaXplLCBNUElfSU5ULCBsb2NhbF9kYXRhLCBsb2NhbF9zaXplLCBNUElfSU5ULCAwLCBNUElfQ09NTV9XT1JMRCk7CgogICAgLy8gTWVhc3VyZSBjb21wdXRhdGlvbiB0aW1lCiAgICBkb3VibGUgc3RhcnRfdGltZSA9IE1QSV9XdGltZSgpOwoKICAgIC8vIENvbXB1dGUgcHJlZml4IHN1bSBsb2NhbGx5IGFuZCBhZGp1c3Qgd2l0aCBvZmZzZXRzCiAgICBpbnQgbG9jYWxfcmVzdWx0W2xvY2FsX3NpemVdOyAvLyBTdGF0aWMgYWxsb2NhdGlvbiBmb3IgbG9jYWwgcmVzdWx0CiAgICBwcmVmaXhfc3VtKGxvY2FsX2RhdGEsIGxvY2FsX3NpemUsIGxvY2FsX3Jlc3VsdCk7CgogICAgLy8gR2F0aGVyIHRoZSByZXN1bHRzIGJhY2sKICAgIHN0YXRpYyBpbnQgcmVzdWx0W0FSUkFZX1NJWkVdOyAvLyBTdGF0aWMgYWxsb2NhdGlvbiBmb3IgdGhlIGZpbmFsIHJlc3VsdAogICAgTVBJX0dhdGhlcihsb2NhbF9yZXN1bHQsIGxvY2FsX3NpemUsIE1QSV9JTlQsIHJlc3VsdCwgbG9jYWxfc2l6ZSwgTVBJX0lOVCwgMCwgTVBJX0NPTU1fV09STEQpOwoKICAgIGRvdWJsZSBlbmRfdGltZSA9IE1QSV9XdGltZSgpOwoKICAgIC8vIFByaW50IHRoZSByZXN1bHQgYW5kIGNvbXB1dGF0aW9uIHRpbWUKICAgIGlmIChyYW5rID09IDApIHsKICAgICAgICBwcmludGYoIlByZWZpeCBTdW06ICIpOwogICAgICAgIHByaW50ZigiJWQgIiwgcmVzdWx0WzEwMDAwMDddKTsKICAgICAgICBwcmludGYoIlxuIik7CiAgICAgICAgcHJpbnRmKCJDb21wdXRhdGlvbiBUaW1lOiAlZiBzZWNvbmRzXG4iLCBlbmRfdGltZSAtIHN0YXJ0X3RpbWUpOwogICAgfQoKICAgIE1QSV9GaW5hbGl6ZSgpOwogICAgcmV0dXJuIDA7Cn0K