jomaora
jomaora

Reputation: 1656

MPI global execution time

I'm working on a little application that multiples an array with a Matrix. It works without any problem. I'm loking for measure the execution time of the application. I can find the individual time of execution of each processes (its starting and ending) but I need the global time.

This is my code:

int main(int argc, char **argv){
    int rang, procesus;
    MPI_Status statut;
    double start, end, max_end = 0, min_start = 10000;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rang);
    MPI_Comm_size(MPI_COMM_WORLD, &procesus);
    MPI_Barrier(MPI_COMM_WORLD);

    start = MPI_Wtime();
    printf("Starting time of process n. %d %f\n",rang, start);
    if(rang==0){
        //Master work
    }else{
        //slaves work
    }
    MPI_Barrier(MPI_COMM_WORLD);
    end = MPI_Wtime();
    printf("Ending time of process n.%d %f\n\n\n",rang, end);

    MPI_Finalize();
//Out of the Parallelized task

    if(min_start > start){
        min_start = start;
        printf("New minumum starting time %f\n", min_start);
    }

    if(max_end < end){
        max_end = end;
        printf("New maximum ending time %f\n", max_end);
    }

    if(rang == 0){
        printf("Start %f\n", min_start);
        printf("End %f\n", max_end);
    }
    return 0;
}

I use the varables min_start and max_end as "global" variables to try to catch the max and min temps of all the processes, but I always get the starting and ending tme of the last process to execute, the ending time is ok, but the starting time is wrong cause the last process was ot the first to start. What am I doing wrong? Can I use a really global variable in MPI for all the processes, and if I can how?

That's what I have as output

Starting time of process n.2. 0.101562
Ending time of process n.2. 0.105469
New minumum starting time 0.101562
New maximum ending time 0.105469

Starting time of process n.3. 0.058594
Ending time of process n.3. 0.062500
New minumum starting time 0.058594
New maximum ending time 0.062500

Starting time of process n. 4. 0.007812
Ending time of process n. 4. 0.011719
New minumum starting time 0.007812
New maximum ending time 0.011719

Starting time of process n.1. 0.148438
Ending time of process n.1. 0.152344
New minumum starting time 0.148438
New maximum ending time 0.152344

Starting time of process n.0. 0.207031 
Ending time of process n.0. 0.210938
New minumum starting time 0.207031
New maximum ending time 0.210938

Start 0.207031
End 0.210938

Upvotes: 21

Views: 31340

Answers (3)

AHL
AHL

Reputation: 493

You can use MPI_REDUCE like this code snippet

 mytime = MPI_Wtime(); /*get time just before work section */

   work(myrank); /*need to create */

   MPI_Barrier(MPI_COMM_WORLD);

   mytime = MPI_Wtime() - mytime; /*get time just after work section*/



/*compute max, min, and average timing statistics*/

MPI_Reduce(&mytime, &maxtime, 1, MPI_DOUBLE,MPI_MAX, 0, MPI_COMM_WORLD);

MPI_Reduce(&mytime, &mintime, 1, MPI_DOUBLE, MPI_MIN, 0,MPI_COMM_WORLD);

MPI_Reduce(&mytime, &avgtime, 1, MPI_DOUBLE, MPI_SUM, 0,MPI_COMM_WORLD);

if (myrank == 0) 

   {

  avgtime /= numprocs;

  printf("Min: %lf Max: %lf Avg: %lf\n", mintime, maxtime,avgtime);
   }

MPI_Finalize ();

MPI_Reduce takes an array of input elements on each process and returns an array of output elements to the root process. The output elements contain the reduced result.

  • MPI_MAX - Returns the maximum element.
  • MPI_MIN - Returns the minimum element.
  • MPI_SUM - Sums the elements.
  • MPI_PROD - Multiplies all elements.
  • MPI_LAND - Performs a logical and across the elements.
  • MPI_LOR - Performs a logical or across the elements.
  • MPI_BAND - Performs a bitwise and across the bits of the elements.
  • MPI_BOR -Performs a bitwise or across the bits of the elements.
  • MPI_MAXLOC -Returns the maximum value and the rank of the process that owns it.
  • MPI_MINLOC - Returns the minimum value and the rank of the process that owns it.
MPI_Reduce(
    void* send_data,
    void* recv_data,
    int count,
    MPI_Datatype datatype,
    MPI_Op op,
    int root,
    MPI_Comm communicator)

Upvotes: 3

Shawn Chin
Shawn Chin

Reputation: 86864

In most cases, it is often enough to simply keep track of the start and end time on the master node and derive the global run time on the the master only.

One thing worth noting is that you must place a barrier before collecting the start time (to make sure all nodes are ready to proceed), and before the end time (to make sure all nodes are done).

double start, end;

MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Barrier(MPI_COMM_WORLD); /* IMPORTANT */
start = MPI_Wtime();

/* ... do work ... */

MPI_Barrier(MPI_COMM_WORLD); /* IMPORTANT */
end = MPI_Wtime();

MPI_Finalize();

if (rank == 0) { /* use time on master node */
    printf("Runtime = %f\n", end-start);
}

Doing the same on all nodes will give the almost the same results with small deviations depending on how quickly each node returns from the MPI_Barrier call. This is usually a very small value relative to most practical runs and can be discounted.

Trying to derive a time using start/end times from different nodes is not worth the effort, and can give your wrong answers if MPI_Wtime does not use a global synchronised clock. Note that synced Wtime is not supported in some MPI implementations (check MPI_WTIME_IS_GLOBAL).

Upvotes: 43

suszterpatt
suszterpatt

Reputation: 8273

MPI_Init() and MPI_Finalize() don't mark the beginning and end of parallel execution, only the beginning and end of where MPI calls are allowed. In MPI, all your processes run parallel from beginning to end and share no global data whatsoever.

You can use MPI_Reduce() to find the minimum starting time and maximum ending time of processes.

Upvotes: 13

Related Questions