1

So let's say that I have created a main-worker program with the following steps:

1 - main sends tasks to all workers

2 - faster workers accomplish tasks and send the results back to the main

3 - main receives the results from the fastest workers and sends new tasks to everyone

4 - faster workers are ready to receive the task, but slower workers have to interrupt or cancel the old, slow, task that they were doing, in order to start the new task at the same time as the faster worker

I know how to do all the steps, except for step 4, where I would have to interrupt what the slower workers are doing in order to proceed to the next task.

Here is an example of an incomplete code that is missing that part:

#include <mpi.h>
#include <iostream>
#include <string>
#include <unistd.h>

using namespace std;

int main(int argc, char* argv[])
{
  MPI_Init(&argc,&argv);

  int rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);


  if (rank == 0) {
    int value = 17;
    string valuec = "Hello";

    for(int i = 1; i < world_size; i++){


        int result = MPI_Send(valuec.c_str(), valuec.length(), MPI_CHAR, i, 0, MPI_COMM_WORLD);
            if (result == MPI_SUCCESS)
          std::cout << "Rank 0 OK!" << std::endl;
    }

    int workersDone = 0;
    MPI_Status status;
    int flag = 0;

    while(1){
        flag=0;
        MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, &status);
        if(flag==1){
            workersDone++;
            cout << "Workers done: " << workersDone << endl;
        }

        if(workersDone >= world_size/2){/* here the main moves on
                                          before all workers are done
                                          */
            cout << "Main breaking" << endl; 
            break;
        }

    }

    /* interruption Here:
                    How do I make the main tell to the slow workers
                    interrupt or cancel what they were doing in order
                    to receive new tasks
                    */

    // New tasks should go here here

  } else if (rank != 0) {
    int receivedMessages = 0;
    while(1){ 
                MPI_Status status;
            int flag = 0;

        MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, &status);

    if(flag==1){
        receivedMessages++;
            int value;
            char buffer[256];
            int result = MPI_Recv(&buffer, 256, MPI_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            cout << rank << " received " << buffer << endl;

            sleep(rank); /* this hypothetical task will be slower
                            in some workers, faster in others. In the
                            final version of code of course this
                            will not be a sleep command, and the time
                            it takes will not be proportional to the
                            process rank.
                            */
        MPI_Send(buffer, sizeof(buffer), MPI_CHAR, 0, 0, MPI_COMM_WORLD);

        cout << rank << " breaking" << endl;

        break; 

    }
 }
}
  MPI_Finalize();
  return 0;
} 
Robin De Schepper
  • 4,942
  • 4
  • 35
  • 56
RDlady
  • 378
  • 2
  • 16
  • you can refer to https://stackoverflow.com/questions/43973504/mpi-asynchronous-broadcast-from-unknown-source. your solution depends whether slave can periodically check for an interruption, or they should be "interrupted" asynchronously (and you will need several threads for that) – Gilles Gouaillardet Oct 25 '17 at 00:34
  • I found that link but it is a little confusing for me. Could you suggest a solution example modifying my code? It doesn't need to work right away, anything getting closer to a solution should help. Either approach you mentioned should work to solve my problem. – RDlady Oct 25 '17 at 16:56
  • i will not write your code for you, but here are some hints. on rank 0, you can `MPI_Recv()` (currently, you basically `MPI_Iprobe()` in a loop, and you never read the message). on other ranks, you can `MPI_Ibcast()` and periodically `MPI_Test()` to check whether you should be interrupted. when a slave completes its job, it should `MPI_Send()` to master. when enough slaves completed their job, master should `MPI_Ibcast(); MPI_Wait();` to notify the slaves. – Gilles Gouaillardet Oct 26 '17 at 12:47
  • Thank you for your help, but let me just clarify one thing: you will not be writting my code for me because this is not even close to the >100,000 lines of code that I have been developing for a large software to simulate rule-based models to characterize complex enzyme networks. So if you write a code sample here I will not take it anywhere, I will just study your example as a template in order to make my own code. – RDlady Oct 26 '17 at 17:38

0 Answers0