#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <mpi.h>
#include "fileio.h"
const int ROOT = 0;
const int TAG = 0;
void ptp_ring_sum(int size, char *input_file, int my_rank, int comm_sz);
double array_sum(int *array, int size);
int main(int argc, char* argv[]) {
int comm_sz, my_rank;
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
if (argc < (comm_sz + 2)) {
if (my_rank == ROOT) {
fprintf(stderr
, "Usage: mpirun -np <p> %s <size> <file for rank 0> ... <file for rank p-1>\n", argv
[0]); }
} else {
ptp_ring_sum
(atoi(argv
[1]), argv
[2 + my_rank
], my_rank
, comm_sz
); }
MPI_Finalize();
return EXIT_SUCCESS;
}
/**
* This function will be called by all the processes in the communicator
* TODO: Calculate the total sum of all the local array sums using point to point communication as follows:
* - process 0 should send its sum to process 1, and receive the total sum from the process with the highest rank
* - process 1 should receive the sum from process 0, add its local_sum to it, and send the result to process 2
* - ...
* - the last process should receive the sum from the second-last process, add its local_sum to it, and send the result to process 0
*/
void ptp_ring_sum(int size, char *input_file, int my_rank, int comm_sz) {
// Allocate memory for the local array
int *local_array = NULL;
local_array = read_array(input_file, &size);
if (!local_array) {
fprintf(stderr
, "Error: Unable to allocate memory for local array.\n"); MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
return;
}
// Print the local array
print_array(local_array, size, "Array");
// Calculate the sum of the local array
double local_sum = array_sum(local_array, size);
print_double(local_sum, "The local sum");
// Free the local array
// Determine the destination and source for sending/receiving sums
int dest = (my_rank + 1) % comm_sz; // Destination is the next process in the ring
int source = (my_rank - 1 + comm_sz) % comm_sz; // Source is the previous process in the ring
if (my_rank == 0) {
// Process 0 starts the chain by sending its sum to process 1
MPI_Send(&local_sum, 1, MPI_DOUBLE, dest, 0, MPI_COMM_WORLD);
printf("Process 0 sent its partial sum to process 1.\n"); // Then it receives the final total sum from the last process
MPI_Recv(&local_sum, 1, MPI_DOUBLE, source, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("Process 0 received the total sum from the last process: %.1f\n", local_sum
); } else {
// All other processes receive sum from the previous process, add to it, and send it to the next
double received_sum = 0.0;
MPI_Recv(&received_sum, 1, MPI_DOUBLE, source, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("Process %d received a partial sum from process %d: %.1f\n", my_rank
, source
, received_sum
);
received_sum += local_sum;
MPI_Send(&received_sum, 1, MPI_DOUBLE, dest, 0, MPI_COMM_WORLD);
printf("Process %d sent its partial sum to process %d.\n", my_rank
, dest
); }
}
/** Calculate the sum of the values in the provided array */
double array_sum(int *arr, int sz) {
double sum = 0;
for (int i = 0; i < sz; i++) {
sum += (double) arr[i];
}
return sum;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8bGltaXRzLmg+CiNpbmNsdWRlIDxtcGkuaD4KI2luY2x1ZGUgImZpbGVpby5oIgoKY29uc3QgaW50IFJPT1QgPSAwOwpjb25zdCBpbnQgVEFHID0gMDsKCnZvaWQgcHRwX3Jpbmdfc3VtKGludCBzaXplLCBjaGFyICppbnB1dF9maWxlLCBpbnQgbXlfcmFuaywgaW50IGNvbW1fc3opOwpkb3VibGUgYXJyYXlfc3VtKGludCAqYXJyYXksIGludCBzaXplKTsKCmludCBtYWluKGludCBhcmdjLCBjaGFyKiBhcmd2W10pIHsKCWludCBjb21tX3N6LCBteV9yYW5rOwoKCU1QSV9Jbml0KE5VTEwsIE5VTEwpOwoJTVBJX0NvbW1fc2l6ZShNUElfQ09NTV9XT1JMRCwgJmNvbW1fc3opOwoJTVBJX0NvbW1fcmFuayhNUElfQ09NTV9XT1JMRCwgJm15X3JhbmspOwogCglpZiAoYXJnYyA8IChjb21tX3N6ICsgMikpIHsKCQlpZiAobXlfcmFuayA9PSBST09UKSB7CgkJCWZwcmludGYoc3RkZXJyLCAiVXNhZ2U6IG1waXJ1biAtbnAgPHA+ICVzIDxzaXplPiA8ZmlsZSBmb3IgcmFuayAwPiAuLi4gPGZpbGUgZm9yIHJhbmsgcC0xPlxuIiwgYXJndlswXSk7CgkJfQoJfSBlbHNlIHsKCQlwdHBfcmluZ19zdW0oYXRvaShhcmd2WzFdKSwgYXJndlsyICsgbXlfcmFua10sIG15X3JhbmssIGNvbW1fc3opOwoJfQoKCU1QSV9GaW5hbGl6ZSgpOwoKCXJldHVybiBFWElUX1NVQ0NFU1M7Cn0KCi8qKgogKiBUaGlzIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGJ5IGFsbCB0aGUgcHJvY2Vzc2VzIGluIHRoZSBjb21tdW5pY2F0b3IgCiAqIFRPRE86IENhbGN1bGF0ZSB0aGUgdG90YWwgc3VtIG9mIGFsbCB0aGUgbG9jYWwgYXJyYXkgc3VtcyB1c2luZyBwb2ludCB0byBwb2ludCBjb21tdW5pY2F0aW9uIGFzIGZvbGxvd3M6CiAqIC0gcHJvY2VzcyAwIHNob3VsZCBzZW5kIGl0cyBzdW0gdG8gcHJvY2VzcyAxLCBhbmQgcmVjZWl2ZSB0aGUgdG90YWwgc3VtIGZyb20gdGhlIHByb2Nlc3Mgd2l0aCB0aGUgaGlnaGVzdCByYW5rIAogKiAtIHByb2Nlc3MgMSBzaG91bGQgcmVjZWl2ZSB0aGUgc3VtIGZyb20gcHJvY2VzcyAwLCBhZGQgaXRzIGxvY2FsX3N1bSB0byBpdCwgYW5kIHNlbmQgdGhlIHJlc3VsdCB0byBwcm9jZXNzIDIKICogLSAuLi4KICogLSB0aGUgbGFzdCBwcm9jZXNzIHNob3VsZCByZWNlaXZlIHRoZSBzdW0gZnJvbSB0aGUgc2Vjb25kLWxhc3QgcHJvY2VzcywgYWRkIGl0cyBsb2NhbF9zdW0gdG8gaXQsIGFuZCBzZW5kIHRoZSByZXN1bHQgdG8gcHJvY2VzcyAwCiAqLwp2b2lkIHB0cF9yaW5nX3N1bShpbnQgc2l6ZSwgY2hhciAqaW5wdXRfZmlsZSwgaW50IG15X3JhbmssIGludCBjb21tX3N6KSB7CiAgICAvLyBBbGxvY2F0ZSBtZW1vcnkgZm9yIHRoZSBsb2NhbCBhcnJheQogICAgaW50ICpsb2NhbF9hcnJheSA9IE5VTEw7CiAgICBsb2NhbF9hcnJheSA9IHJlYWRfYXJyYXkoaW5wdXRfZmlsZSwgJnNpemUpOwogICAgaWYgKCFsb2NhbF9hcnJheSkgewogICAgICAgIGZwcmludGYoc3RkZXJyLCAiRXJyb3I6IFVuYWJsZSB0byBhbGxvY2F0ZSBtZW1vcnkgZm9yIGxvY2FsIGFycmF5LlxuIik7CiAgICAgICAgTVBJX0Fib3J0KE1QSV9DT01NX1dPUkxELCBFWElUX0ZBSUxVUkUpOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICAvLyBQcmludCB0aGUgbG9jYWwgYXJyYXkKICAgIHByaW50X2FycmF5KGxvY2FsX2FycmF5LCBzaXplLCAiQXJyYXkiKTsKCiAgICAvLyBDYWxjdWxhdGUgdGhlIHN1bSBvZiB0aGUgbG9jYWwgYXJyYXkKICAgIGRvdWJsZSBsb2NhbF9zdW0gPSBhcnJheV9zdW0obG9jYWxfYXJyYXksIHNpemUpOwogICAgcHJpbnRfZG91YmxlKGxvY2FsX3N1bSwgIlRoZSBsb2NhbCBzdW0iKTsKCiAgICAvLyBGcmVlIHRoZSBsb2NhbCBhcnJheQogICAgZnJlZShsb2NhbF9hcnJheSk7CgogICAgLy8gRGV0ZXJtaW5lIHRoZSBkZXN0aW5hdGlvbiBhbmQgc291cmNlIGZvciBzZW5kaW5nL3JlY2VpdmluZyBzdW1zCiAgICBpbnQgZGVzdCA9IChteV9yYW5rICsgMSkgJSBjb21tX3N6OyAvLyBEZXN0aW5hdGlvbiBpcyB0aGUgbmV4dCBwcm9jZXNzIGluIHRoZSByaW5nCiAgICBpbnQgc291cmNlID0gKG15X3JhbmsgLSAxICsgY29tbV9zeikgJSBjb21tX3N6OyAvLyBTb3VyY2UgaXMgdGhlIHByZXZpb3VzIHByb2Nlc3MgaW4gdGhlIHJpbmcKCiAgICBpZiAobXlfcmFuayA9PSAwKSB7CiAgICAgICAgLy8gUHJvY2VzcyAwIHN0YXJ0cyB0aGUgY2hhaW4gYnkgc2VuZGluZyBpdHMgc3VtIHRvIHByb2Nlc3MgMQogICAgICAgIE1QSV9TZW5kKCZsb2NhbF9zdW0sIDEsIE1QSV9ET1VCTEUsIGRlc3QsIDAsIE1QSV9DT01NX1dPUkxEKTsKICAgICAgICBwcmludGYoIlByb2Nlc3MgMCBzZW50IGl0cyBwYXJ0aWFsIHN1bSB0byBwcm9jZXNzIDEuXG4iKTsKICAgICAgICAvLyBUaGVuIGl0IHJlY2VpdmVzIHRoZSBmaW5hbCB0b3RhbCBzdW0gZnJvbSB0aGUgbGFzdCBwcm9jZXNzCiAgICAgICAgTVBJX1JlY3YoJmxvY2FsX3N1bSwgMSwgTVBJX0RPVUJMRSwgc291cmNlLCAwLCBNUElfQ09NTV9XT1JMRCwgTVBJX1NUQVRVU19JR05PUkUpOwogICAgICAgIHByaW50ZigiUHJvY2VzcyAwIHJlY2VpdmVkIHRoZSB0b3RhbCBzdW0gZnJvbSB0aGUgbGFzdCBwcm9jZXNzOiAlLjFmXG4iLCBsb2NhbF9zdW0pOwogICAgfSBlbHNlIHsKICAgICAgICAvLyBBbGwgb3RoZXIgcHJvY2Vzc2VzIHJlY2VpdmUgc3VtIGZyb20gdGhlIHByZXZpb3VzIHByb2Nlc3MsIGFkZCB0byBpdCwgYW5kIHNlbmQgaXQgdG8gdGhlIG5leHQKICAgICAgICBkb3VibGUgcmVjZWl2ZWRfc3VtID0gMC4wOwogICAgICAgIE1QSV9SZWN2KCZyZWNlaXZlZF9zdW0sIDEsIE1QSV9ET1VCTEUsIHNvdXJjZSwgMCwgTVBJX0NPTU1fV09STEQsIE1QSV9TVEFUVVNfSUdOT1JFKTsKICAgICAgICBwcmludGYoIlByb2Nlc3MgJWQgcmVjZWl2ZWQgYSBwYXJ0aWFsIHN1bSBmcm9tIHByb2Nlc3MgJWQ6ICUuMWZcbiIsIG15X3JhbmssIHNvdXJjZSwgcmVjZWl2ZWRfc3VtKTsKCiAgICAgICAgcmVjZWl2ZWRfc3VtICs9IGxvY2FsX3N1bTsKICAgICAgICBNUElfU2VuZCgmcmVjZWl2ZWRfc3VtLCAxLCBNUElfRE9VQkxFLCBkZXN0LCAwLCBNUElfQ09NTV9XT1JMRCk7CiAgICAgICAgcHJpbnRmKCJQcm9jZXNzICVkIHNlbnQgaXRzIHBhcnRpYWwgc3VtIHRvIHByb2Nlc3MgJWQuXG4iLCBteV9yYW5rLCBkZXN0KTsKICAgIH0KfQoKLyoqIENhbGN1bGF0ZSB0aGUgc3VtIG9mIHRoZSB2YWx1ZXMgaW4gdGhlIHByb3ZpZGVkIGFycmF5ICovCmRvdWJsZSBhcnJheV9zdW0oaW50ICphcnIsIGludCBzeikgewoJZG91YmxlIHN1bSA9IDA7Cglmb3IgKGludCBpID0gMDsgaSA8IHN6OyBpKyspIHsKCQkgc3VtICs9IChkb3VibGUpIGFycltpXTsKCX0KCglyZXR1cm4gc3VtOwp9Cg==