manual_all2all_fr.c

/******************************************************************/
/*                                                                */
/* Questions 3-5: Alltoall                                        */
/*                                                                */
/******************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <mpi.h>
#include <sys/time.h>

#define BUFLEN 65536

long ms_time(void) 
{
  struct timeval tv;

  gettimeofday(&tv, NULL);
  return(tv.tv_sec*1000 + tv.tv_usec/1000);
}

void long_computation(void) 
{
   long now=ms_time();
   while(ms_time()<now+4000) 
     {
     }
}

void my_broadcast(void *buffer, int count, MPI_Datatype datatype, int root) {
  int my_id, nb_proc;
  MPI_Status status;
  int i;

  MPI_Comm_rank(MPI_COMM_WORLD,&my_id);
  MPI_Comm_size(MPI_COMM_WORLD,&nb_proc);
  
  if (my_id == root) {
    for (i=0; i<nb_proc; i++) {
      if (i != root) {
	MPI_Send(buffer, count, datatype,i,0,MPI_COMM_WORLD);
      }
    }
  } else {
    MPI_Recv(buffer,count,datatype, root, 0, MPI_COMM_WORLD, &status);
  }
}

/*
 * On suppose que les données à envoyer sont dans buffer[mon_rang]
 * et qu'on va recevoir les données du processus i dand buffer[i].
 * On suppose également qu'on ne manipule que des entiers.
 */

void my_alltoall(int *buffer, int count, MPI_Datatype datatype) {
  int root, nb_proc;
  
  MPI_Comm_size(MPI_COMM_WORLD,&nb_proc);

  for(root=0; root<nb_proc; root++) {
    my_broadcast(&(buffer[root]), count, datatype, root);
  }
}


void my_asynchronous_all2all(int *buffer, int count, MPI_Datatype datatype) {
  int my_id, nb_proc;
  int i;
  int nb_requests;
  MPI_Request *send_requests;
  MPI_Request *recv_requests;
  MPI_Status *status_array;


  MPI_Comm_rank(MPI_COMM_WORLD,&my_id);
  MPI_Comm_size(MPI_COMM_WORLD,&nb_proc);

  send_requests = (MPI_Request*) malloc((nb_proc - 1) * sizeof(MPI_Request));
  recv_requests = (MPI_Request*) malloc((nb_proc - 1) * sizeof(MPI_Request));
  status_array = (MPI_Status*) malloc((nb_proc - 1) * sizeof(MPI_Status));
  
  nb_requests = 0;
  for(i=0; i<nb_proc; i++) {
    if (i != my_id) { 
      /* 
       * On planifie l'envoi vers le processus i et la réception depuis le processus i
       */
      MPI_Isend(&buffer[my_id], count, datatype, i, 1, MPI_COMM_WORLD, &send_requests[nb_requests]);
      MPI_Irecv(&buffer[i], count, datatype, i, 1, MPI_COMM_WORLD, &recv_requests[nb_requests]);
      nb_requests++;
    }
  }
 

  /* On attend que toutes les émissions et toutes les réceptions qu'on a planifiés soient terminées */

  MPI_Waitall(nb_requests,send_requests,status_array);
  MPI_Waitall(nb_requests,recv_requests,status_array);
  
}

int main(int argc, char **argv) 
{
  int nb_proc;
  int my_id;
  int *buffer;
  long int start_time, end_time;
  int i;

  MPI_Init(&argc,&argv);
  MPI_Comm_size(MPI_COMM_WORLD,&nb_proc);
  MPI_Comm_rank(MPI_COMM_WORLD,&my_id);
 
  buffer = (int*) malloc(nb_proc * sizeof(int));

  start_time = ms_time();

  /*
   * On commence par mettre notre rang i dans buffer[i], et on met des zéros ailleurs
   */
  for(i=0;i<nb_proc;i++) {
    buffer[i] = 0;
  }
  buffer[my_id] = my_id;
  /*
   * Chacun écrit son buffer avant le alltoall
   */  
  printf("[proc P%d] Avant le alltoall, mon buffer est  ",my_id);
  for(i=0;i<nb_proc;i++) {
    printf("%d ",buffer[i]);
  }
  printf("\n");


  /* On veut maintenant partager ces valeurs */

  /* Question 3. En utilisant des communications synchrones */
    my_alltoall(buffer, 1, MPI_INT);

  /* Question 4. En utilisant des communications asynchrones */
  //  my_asynchronous_all2all(buffer, 1, MPI_INT);

  /* Question 5.En utilisant une fonction MPI prédéfinie */
  //  MPI_Allgather(&buffer[my_id], 1, MPI_INT, buffer, 1, MPI_INT, MPI_COMM_WORLD);

  
  /*
   * Chacun écrit son buffer après le alltoall
   */  
  printf("[proc P%d] Après le alltoall, mon buffer est ",my_id);
  for(i=0;i<nb_proc;i++) {
    printf("%d ",buffer[i]);
  }
  printf("\n");


  long_computation();
  end_time = ms_time();
  printf("[proc P%d] Terminé en %ld millisecondes.\n", my_id, end_time - start_time);


  MPI_Finalize();

  return (0);
}

Generated by GNU enscript 1.6.3.