manual_all2all_eng.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);
  }
}

/*
 * We assume that the data to be sent is at buffer[my_rank]
 * and we will receive the data from process i at buffer[i]
 * We also assume that the buffer contains integers.
 */

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) { 
      /* 
       * We planify the send and receive operation from and to process 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++;
    }
  }
 

  /* We wait for all sending and receiving requests to end */ 
  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();

  /*
   * We first put our id in  buffer[id], and set everything else to zero
   */
  for(i=0;i<nb_proc;i++) {
    buffer[i] = 0;
  }
  buffer[my_id] = my_id;
  /*
   * Everybody prints its buffer before the Alltoall
   */  
  printf("[proc P%d] Before all2all, my buffer is ",my_id);
  for(i=0;i<nb_proc;i++) {
    printf("%d ",buffer[i]);
  }
  printf("\n");


  /* Now we want to share this buffer */

  /* Question 3. Using synchronous communications */
    my_alltoall(buffer, 1, MPI_INT);

  /* Question 4. Using asynchronous communications */
  //  my_asynchronous_all2all(buffer, 1, MPI_INT);

  /* Question 5. Using built-in MPI functions */
  //  MPI_Allgather(&buffer[my_id], 1, MPI_INT, buffer, 1, MPI_INT, MPI_COMM_WORLD);

  
  /*
   * Everybody prints its buffer after the Alltoall
   */  
  printf("[proc P%d] After all2all, my buffer is ",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] Done within %ld milliseconds.\n", my_id, end_time - start_time);


  MPI_Finalize();

  return (0);
}

Generated by GNU enscript 1.6.3.