You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
5.5 KiB
165 lines
5.5 KiB
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <mpi.h>
|
|
#include <stdbool.h>
|
|
#include <limits.h>
|
|
|
|
#define INPUTFILE "sample1_e.in"
|
|
// Avoids aggresive memory reallocation at the beginning of buffer growth sequence
|
|
#define INIT_COUNT 8
|
|
// Optimal exponential buffer growth factor, 2 is sometimes used to
|
|
#define GROWTH_FACTOR 1.5
|
|
|
|
// Macro for counting the lenght of an array
|
|
#define COUNT(x) ((int) (sizeof(x) / sizeof(x[0])))
|
|
|
|
|
|
void *my_malloc(size_t size);
|
|
void *my_realloc(void *p, size_t size);
|
|
FILE *my_fopen(const char *filename, const char *mode);
|
|
bool is_mpi_defined(int n);
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int size, rank, slave, i, n, value, count = 0;
|
|
float fvalue;
|
|
|
|
MPI_Status status;
|
|
|
|
MPI_Init(&argc, &argv);
|
|
MPI_Comm_size(MPI_COMM_WORLD, &size);
|
|
|
|
if (size == 4) {
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
|
|
|
|
if (rank == 0) {
|
|
|
|
int number, max = INIT_COUNT;
|
|
// Allocate enough memory for INIT_COUNT numbers
|
|
int *numbers = my_malloc(max * sizeof(int *));
|
|
//int num[10];
|
|
FILE *file = my_fopen(INPUTFILE, "r");
|
|
|
|
// Read lines of numbers until an EOF or a character is read
|
|
while (fscanf(file, "%d", &number) == 1) {
|
|
// Buffer space check
|
|
if (max == count) {
|
|
// Grow buffer exponentially
|
|
max *= GROWTH_FACTOR;
|
|
numbers = my_realloc(numbers, max * sizeof(int *));
|
|
}
|
|
|
|
// Store the read number to the array in memory
|
|
numbers[count++] = number;
|
|
}
|
|
|
|
printf(" Sending numbers: ");
|
|
for (i = 0; i < count; i++)
|
|
printf("%d ", numbers[i]);
|
|
|
|
|
|
printf("\n -----------------------------");
|
|
for (slave = 1; slave < size; slave++) {
|
|
printf("\n from master %d to slave %d", rank, slave);
|
|
MPI_Send(numbers, count, MPI_INT, slave, 1, MPI_COMM_WORLD);
|
|
}
|
|
printf("\n\n Receiving the results from slaves");
|
|
printf("\n ---------------------------------");
|
|
MPI_Recv(&value, 1, MPI_INT, 1, 11, MPI_COMM_WORLD, &status);
|
|
printf("\n Minimum %4d from slave 1", value);
|
|
MPI_Recv(&value, 1, MPI_INT, 2, 21, MPI_COMM_WORLD, &status);
|
|
printf("\n Sum\t %4d from slave 2", value);
|
|
MPI_Recv(&value, 1, MPI_INT, 1, 12, MPI_COMM_WORLD, &status);
|
|
printf("\n Maximum %4d from slave 1", value);
|
|
MPI_Recv(&fvalue, 1, MPI_FLOAT, 2, 22, MPI_COMM_WORLD, &status);
|
|
printf("\n Average %4.2f from slave 2", fvalue);
|
|
MPI_Recv(&fvalue, 1, MPI_FLOAT, 3, 31, MPI_COMM_WORLD, &status);
|
|
printf("\n H. mean %4.2f from slave 3\n", fvalue);
|
|
}
|
|
else {
|
|
MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
|
|
MPI_Get_count(&status, MPI_INT, &n);
|
|
|
|
is_mpi_defined(n);
|
|
int numbers[n];
|
|
count = COUNT(numbers);
|
|
|
|
if (rank == 1) {
|
|
MPI_Recv(numbers, n, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
|
|
//MPI_Recv(numbers, n, MPI_INT, status.MPI_SOURCE, status.MPI_TAG, MPI_COMM_WORLD, &status);
|
|
value = INT_MAX;
|
|
for (i = 0; i < count; i++) {
|
|
if (value > numbers[i]) {
|
|
value = numbers[i];
|
|
}
|
|
}
|
|
MPI_Send(&value, 1, MPI_INT, 0, 11, MPI_COMM_WORLD);
|
|
value = 0;
|
|
for (i = 0; i < count; i++) {
|
|
if (value < numbers[i]) {
|
|
value = numbers[i];
|
|
}
|
|
}
|
|
MPI_Send(&value, 1, MPI_INT, 0, 12, MPI_COMM_WORLD);
|
|
}
|
|
else if (rank == 2) {
|
|
MPI_Recv(numbers, n, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
|
|
value = 0;
|
|
for (i = 0; i < count; i++) {
|
|
value = value + numbers[i];
|
|
}
|
|
MPI_Send(&value, 1, MPI_INT, 0, 21, MPI_COMM_WORLD);
|
|
fvalue = (float) value / count;
|
|
MPI_Send(&fvalue, 1, MPI_FLOAT, 0, 22, MPI_COMM_WORLD);
|
|
}
|
|
else {
|
|
MPI_Recv(numbers, n, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
|
|
fvalue = 0.0;
|
|
for (i = 0; i < count; i++) {
|
|
fvalue += 1.0 / numbers[i];
|
|
}
|
|
fvalue = (float) count / fvalue;
|
|
MPI_Send(&fvalue, 1, MPI_FLOAT, 0, 31, MPI_COMM_WORLD);
|
|
}
|
|
}
|
|
}
|
|
MPI_Finalize();
|
|
return (0);
|
|
}
|
|
|
|
|
|
void *my_malloc(size_t size) {
|
|
void *p = malloc(size);
|
|
if (p == NULL) {
|
|
printf("Memory allocation unsuccessful.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
|
|
void *my_realloc(void *p, size_t size) {
|
|
void *temp = realloc(p, size);
|
|
if (temp == NULL) {
|
|
printf("Insufficient memory; can't add more items.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
return temp;
|
|
}
|
|
|
|
|
|
FILE *my_fopen(const char *filename, const char *mode) {
|
|
FILE *file = fopen(filename, mode);
|
|
if (file == NULL) {
|
|
printf("File %s could not be opened.\n", filename);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
return file;
|
|
}
|
|
|
|
bool is_mpi_defined(int n) {
|
|
if (n == MPI_UNDEFINED) {
|
|
printf("MPI encountered undefined integer and terminated.");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
return true;
|
|
}
|
|
|