224 lines
4.5 KiB
C++
224 lines
4.5 KiB
C++
# include <cstdlib>
|
|
# include <iomanip>
|
|
# include <iostream>
|
|
# include <mpi.h>
|
|
|
|
using namespace std;
|
|
|
|
int main ( int argc, char *argv[] );
|
|
void ring_io ( int p, int id );
|
|
|
|
//****************************************************************************80
|
|
|
|
int main ( int argc, char *argv[] )
|
|
|
|
//****************************************************************************80
|
|
//
|
|
// Purpose:
|
|
//
|
|
// MAIN is the main program for RING_MPI.
|
|
//
|
|
// Discussion:
|
|
//
|
|
// RING_MPI sends messages of various size from process 0 to 1 to 2 to
|
|
// ...the last process and then back to 0.
|
|
//
|
|
// Licensing:
|
|
//
|
|
// This code is distributed under the GNU LGPL license.
|
|
//
|
|
// Modified:
|
|
//
|
|
// 16 June 2016
|
|
//
|
|
// Author:
|
|
//
|
|
// John Burkardt
|
|
//
|
|
// Reference:
|
|
//
|
|
// Peter Pacheco,
|
|
// Parallel Programming with MPI,
|
|
// Morgan Kaufman, 1996,
|
|
// ISBN: 1558603395,
|
|
// LC: QA76.642.P3.
|
|
//
|
|
{
|
|
int error;
|
|
int id;
|
|
int p;
|
|
//
|
|
// Initialize MPI.
|
|
//
|
|
MPI_Init ( &argc, &argv );
|
|
//
|
|
// Get the number of processes.
|
|
//
|
|
MPI_Comm_size ( MPI_COMM_WORLD, &p );
|
|
//
|
|
// Get the individual process ID.
|
|
//
|
|
MPI_Comm_rank ( MPI_COMM_WORLD, &id );
|
|
//
|
|
// Print a message.
|
|
//
|
|
if ( id == 0 )
|
|
{
|
|
cout << "\n";
|
|
cout << "RING_MPI:\n";
|
|
cout << " C++/MPI version\n";
|
|
cout << " Measure time required to transmit data around\n";
|
|
cout << " a ring of processes\n";
|
|
cout << "\n";
|
|
cout << " The number of processes is " << p << "\n";
|
|
}
|
|
|
|
ring_io ( p, id );
|
|
//
|
|
// Shut down MPI.
|
|
//
|
|
MPI_Finalize ( );
|
|
//
|
|
// Terminate.
|
|
//
|
|
if ( id == 0 )
|
|
{
|
|
cout << "\n";
|
|
cout << "RING_MPI:\n";
|
|
cout << " Normal end of execution.\n";
|
|
}
|
|
return 0;
|
|
}
|
|
//****************************************************************************80
|
|
|
|
void ring_io ( int p, int id )
|
|
|
|
//****************************************************************************80
|
|
//
|
|
// Purpose:
|
|
//
|
|
// RING_IO carries out the tasks of process ID, of a total of P processes.
|
|
//
|
|
// Licensing:
|
|
//
|
|
// This code is distributed under the GNU LGPL license.
|
|
//
|
|
// Modified:
|
|
//
|
|
// 20 October 2012
|
|
//
|
|
// Author:
|
|
//
|
|
// John Burkardt
|
|
//
|
|
// Reference:
|
|
//
|
|
// Peter Pacheco,
|
|
// Parallel Programming with MPI,
|
|
// Morgan Kaufman, 1996,
|
|
// ISBN: 1558603395,
|
|
// LC: QA76.642.P3.
|
|
//
|
|
{
|
|
int dest;
|
|
int i;
|
|
int j;
|
|
int n;
|
|
int n_test[5] = { 100, 1000, 10000, 100000, 1000000 };
|
|
int n_test_num = 5;
|
|
int source;
|
|
MPI_Status status;
|
|
double tave;
|
|
int test;
|
|
int test_num = 10;
|
|
double tmax;
|
|
double tmin;
|
|
double wtime;
|
|
double *x;
|
|
|
|
if ( id == 0 )
|
|
{
|
|
cout << "\n";
|
|
cout << " Timings based on " << test_num << " experiments\n";
|
|
cout << " N double precision values were sent\n";
|
|
cout << " in a ring transmission starting and ending at process 0\n";
|
|
cout << " and using a total of " << p << " processes.\n";
|
|
cout << "\n";
|
|
cout << " N T min T ave T max\n";
|
|
cout << "\n";
|
|
}
|
|
//
|
|
// Choose message size.
|
|
//
|
|
for ( i = 0; i < n_test_num; i++ )
|
|
{
|
|
n = n_test[i];
|
|
|
|
x = new double[n];
|
|
//
|
|
// Process 0 sends very first message,
|
|
// then waits to receive the "echo" that has gone around the world.
|
|
//
|
|
if ( id == 0 )
|
|
{
|
|
dest = 1;
|
|
source = p - 1;
|
|
|
|
tave = 0.0;
|
|
tmin = 1.0E+30;
|
|
tmax = 0.0;
|
|
|
|
for ( test = 1; test <= test_num; test++ )
|
|
{
|
|
//
|
|
// Just in case, set the entries of X in a way that identifies
|
|
// which iteration of the test is being carried out.
|
|
//
|
|
for ( j = 0; j < n; j++ )
|
|
{
|
|
x[j] = ( double ) ( test + j );
|
|
}
|
|
|
|
wtime = MPI_Wtime ( );
|
|
MPI_Send ( x, n, MPI_DOUBLE, dest, 0, MPI_COMM_WORLD );
|
|
MPI_Recv ( x, n, MPI_DOUBLE, source, 0, MPI_COMM_WORLD, &status );
|
|
wtime = MPI_Wtime ( ) - wtime;
|
|
//
|
|
// Record the time it took.
|
|
//
|
|
tave = tave + wtime;
|
|
if ( wtime < tmin )
|
|
{
|
|
tmin = wtime;
|
|
}
|
|
if ( tmax < wtime )
|
|
{
|
|
tmax = wtime;
|
|
}
|
|
}
|
|
|
|
tave = tave / ( double ) ( test_num );
|
|
cout << " " << setw(8) << n
|
|
<< " " << setw(14) << tmin
|
|
<< " " << setw(14) << tave
|
|
<< " " << setw(14) << tmax << "\n";
|
|
}
|
|
//
|
|
// Worker ID must receive first from ID-1, then send to ID+1.
|
|
// else
|
|
{
|
|
source = id - 1;
|
|
dest = ( ( id + 1 ) % p );
|
|
|
|
for ( test = 1; test <= test_num; test++ )
|
|
{
|
|
MPI_Recv ( x, n, MPI_DOUBLE, source, 0, MPI_COMM_WORLD, &status );
|
|
MPI_Send ( x, n, MPI_DOUBLE, dest, 0, MPI_COMM_WORLD );
|
|
}
|
|
}
|
|
delete [] x;
|
|
}
|
|
|
|
return;
|
|
}
|