137 lines
3.9 KiB
C
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;
|
||
|
}
|