[C - MPI] Esercizio parallelismo

hee136
Per la prossima lezione di esercizi abbiamo da completare il seguente codice.
Per chi non ha voglia di leggere tutto, dobbiamo completare da soli le funzioni in rosso.

#include <mpi.h>

#define WORKTAG 1
#define DIETAG 2


/* Local functions */

static void master(void);
static void slave(void);
static unit_of_work_t get_next_work_item(void);
static void process_results(unit_result_t result);
static unit_result_t do_work(unit_of_work_t work);


int
main(int argc, char **argv)
{
  int myrank;

  /* Initialize MPI */

  MPI_Init(&argc, &argv);

  /* Find out my identity in the default communicator */

  MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
  if (myrank == 0) {
    master();
  } else {
    slave();
  }

  /* Shut down MPI */

  MPI_Finalize();
  return 0;
}


static void
master(void)
{
  int ntasks, rank;
  unit_of_work_t work;
  unit_result_t result;
  MPI_Status status;

  /* Find out how many processes there are in the default
     communicator */

  MPI_Comm_size(MPI_COMM_WORLD, &ntasks);

  /* Seed the slaves; send one unit of work to each slave. */

  for (rank = 1; rank < ntasks; ++rank) {

    /* Find the next item of work to do */

    work = get_next_work_item();

    /* Send it to each rank */

    MPI_Send(&work,             /* message buffer */
             1,                 /* one data item */
             MPI_INT,           /* data item is an integer */
             rank,              /* destination process rank */
             WORKTAG,           /* user chosen message tag */
             MPI_COMM_WORLD);   /* default communicator */
  }

  /* Loop over getting new work requests until there is no more work
     to be done */

  work = get_next_work_item();
  while (work != NULL) {

    /* Receive results from a slave */

    MPI_Recv(&result,           /* message buffer */
             1,                 /* one data item */
             MPI_DOUBLE,        /* of type double real */
             MPI_ANY_SOURCE,    /* receive from any sender */
             MPI_ANY_TAG,       /* any type of message */
             MPI_COMM_WORLD,    /* default communicator */
             &status);          /* info about the received message */

    /* Send the slave a new work unit */

    MPI_Send(&work,             /* message buffer */
             1,                 /* one data item */
             MPI_INT,           /* data item is an integer */
             status.MPI_SOURCE, /* to who we just received from */
             WORKTAG,           /* user chosen message tag */
             MPI_COMM_WORLD);   /* default communicator */

    /* Get the next unit of work to be done */

    work = get_next_work_item();
  }

  /* There's no more work to be done, so receive all the outstanding
     results from the slaves. */

  for (rank = 1; rank < ntasks; ++rank) {
    MPI_Recv(&result, 1, MPI_DOUBLE, MPI_ANY_SOURCE,
             MPI_ANY_TAG, MPI_COMM_WORLD, &status);
  }

  /* Tell all the slaves to exit by sending an empty message with the
     DIETAG. */

  for (rank = 1; rank < ntasks; ++rank) {
    MPI_Send(0, 0, MPI_INT, rank, DIETAG, MPI_COMM_WORLD);
  }
}


static void 
slave(void)
{
  unit_of_work_t work;
  unit_result_t results;
  MPI_Status status;

  while (1) {

    /* Receive a message from the master */

    MPI_Recv(&work, 1, MPI_INT, 0, MPI_ANY_TAG,
             MPI_COMM_WORLD, &status);

    /* Check the tag of the received message. */

    if (status.MPI_TAG == DIETAG) {
      return;
    }

    /* Do the work */

    result = do_work(work);

    /* Send the result back */

    MPI_Send(&result, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
  }
}


static unit_of_work_t 
get_next_work_item(void)
{
  /* Fill in with whatever is relevant to obtain a new unit of work
     suitable to be given to a slave. */
}


static void 
process_results(unit_result_t result)
{
  /* Fill in with whatever is relevant to process the results returned
     by the slave */
}

static unit_result_t
do_work(unit_of_work_t work)
{
  /* Fill in with whatever is necessary to process the work and
     generate a result */
}


Link: http://www.lam-mpi.org/tutorials/one-step/ezstart.php



Non ho capito cosa devo fare con i tipi di dato "unit_of_work_t" e "unit_result_t".
Devo definirli con una struct/classe?

Risposte
hee136
Il codice del precedente post è quello originale.
Prima dei prototipi delle funzioni in rosso (quindi fuori dal main), ho definito i tipi di dato con due struct.

struct unit_of_work_t {
...

struct unit_result_t {
...


Riporto gli errori che ottengo:

[LIST]
Riga codice: static unit_of_work_t get_next_work_item(void);
Errore: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘get_next_work_item[/LIST]
[LIST]
Riga: static void process_results(unit_result_t result);
Errore: expected ‘)’ before ‘result’[/LIST]
[LIST]
Riga: unit_of_work_t work;
Errore: in function Master
‘unit_of_work_t’ undeclared (first use in this function)
(Each undeclared identifier is reported only once
for each function it appears in.)
expected ‘;’ before ‘work’[/LIST]


Dopo aver risolto gli errori, mi basta definire il comportamento delle tre funzioni ed ho finito?

apatriarca
Se stai programmando in C, allora devi sempre scrivere "struct" davanti al tag della struttura oppure usare un typedef. Cioè
static struct unit_of_work_t 
get_next_work_item(void)

oppure
typedef struct unit_of_work_t unit_of_work_t;
struct unit_of_work_t {
    // ...
};

hee136
"apatriarca":
Se stai programmando in C, allora devi sempre scrivere "struct" davanti al tag della struttura oppure usare un typedef. Cioè
static struct unit_of_work_t 
get_next_work_item(void)

oppure
typedef struct unit_of_work_t unit_of_work_t;
struct unit_of_work_t {
    // ...
};


Risolto! :D

Grazie

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.