TP-calcul-parallele/BE/01_RingD/ringd.c
2023-06-23 19:34:09 +02:00

137 lines
3.9 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
int comm_size;
MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
if (comm_size % 2 != 0)
{
printf("This application is meant to be run with an even number of MPI processes, not %d.\n", comm_size);
MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
}
// Get my rank in the global communicator
int my_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
// Determine the colour and key based on whether my rank is even.
char subcommunicator;
int colour;
int key;
if (my_rank % 2 == 0)
{
subcommunicator = 'E';
colour = 0;
key = my_rank;
}
else
{
subcommunicator = 'O';
colour = 1;
key = comm_size - my_rank;
}
// Split of the global communicator
MPI_Comm new_comm;
MPI_Comm_split(MPI_COMM_WORLD, colour, key, &new_comm);
int my_new_comm_rank, new_comm_size;
// Get my rank in the new communicator
MPI_Comm_rank(new_comm, &my_new_comm_rank);
// Get the size of the new communicator
MPI_Comm_size(new_comm, &new_comm_size);
// Print my new rank and new communicator
printf("[MPI process %d] I am now MPI process %d in subcommunicator %c.\n", my_rank, my_new_comm_rank, subcommunicator);
// barriere pour clean un peu le stdout
// MPI_Barrier(MPI_COMM_WORLD);
int previous, next;
// determine my neighbours according to my rank in my subcommunicator
if (my_new_comm_rank == 0)
{
previous = new_comm_size - 1;
next = my_new_comm_rank + 1;
}
else if (my_new_comm_rank == new_comm_size - 1)
{
previous = my_new_comm_rank - 1;
next = 0;
}
else
{
previous = my_new_comm_rank - 1;
next = my_new_comm_rank + 1;
}
// printf("[MPI process %d] new %d previous %d next %d in subcommunicator %c.\n", my_rank, my_new_comm_rank, previous, next, subcommunicator);
float value = 1.0;
MPI_Status status;
// Even: clockwise + multiplication
if (subcommunicator == 'E')
{
// receive value from previous node
if (my_new_comm_rank != 0)
{
MPI_Recv(&value, 1, MPI_FLOAT, previous, 0, new_comm, &status);
printf("[MPI process %d_%c] RECEIVED from process %d of %d, value = %f\n", my_rank, subcommunicator, my_new_comm_rank, new_comm_size, value);
value = value * 2.0;
printf("[MPI process %d_%c] UPDATE, value = %f\n", my_rank, subcommunicator, value);
}
else
{
printf("[MPI process %d_%c] START, value = %f\n", my_rank, subcommunicator, value);
}
// send value to next node
if (my_new_comm_rank != new_comm_size - 1)
{
MPI_Send(&value, 1, MPI_FLOAT, next, 0, new_comm);
printf("[MPI process %d_%c] SENT to process %d of %d, value = %f\n", my_rank, subcommunicator, my_new_comm_rank, new_comm_size, value);
}
}
// Odd: counter-clockwise + division
if (subcommunicator == 'O')
{
// receive value from next node
if (my_new_comm_rank != 0)
{
MPI_Recv(&value, 1, MPI_FLOAT, next, 0, new_comm, &status);
printf("[MPI process %d_%c] RECEIVED from process %d of %d, value = %f\n", my_rank, subcommunicator, my_new_comm_rank, new_comm_size, value);
value = value / 2.0;
printf("[MPI process %d_%c] UPDATE, value = %f\n", my_rank, subcommunicator, value);
}
else
{
printf("[MPI process %d_%c] START, value = %f\n", my_rank, subcommunicator, value);
}
// send value to previous node
if (my_new_comm_rank != 1)
{
MPI_Send(&value, 1, MPI_FLOAT, previous, 0, new_comm);
printf("[MPI process %d_%c] SENT to process %d of %d, value = %f\n", my_rank, subcommunicator, my_new_comm_rank, new_comm_size, value);
}
}
// barrière pour clean un peu le stdout
// MPI_Barrier(MPI_COMM_WORLD);
// the end
printf("[MPI process %d_%c] The End\n", my_rank, subcommunicator);
// Free the communicator
MPI_Finalize();
return EXIT_SUCCESS;
}