Re: gtk+ and MPI



Hi,

As requested, I've attached some trivial example code. Actually two pieces of trivial code. How you need the GUI and MPI portions of your code to interact will determine which is most appropriate. The first attachment, hello_world_mpi3.c, contains the code that Filipe is probably most interested in. I hope that the fact that both examples work is a sufficient answer to Jim's queries.

This code works with LAM/MPI, and I assume that it will work with other implementations too.

One comment that I would make is that it is a good idea to choose your master process such that X communication is avoided, if possible. (i.e. don't use "if (rank==0)". Instead, use MPI_Get_processor_name() and compare that to the localhost name)

Stewart.
--
____________________________________________________________________
Stewart Adcock   stewart linux-domain com   www.stewart-adcock.co.uk
Dept. Chemistry & Biochemistry, University of California, San Diego
4234 Urey Hall, 9500 Gilman Drive, La Jolla, CA 92093-0365 USA
lab: +1 858 534 0956 home: +1 858 453 2577

/******************************************************
 Stewart Adcock, 3 Feb 2002

 Example where all MPI communication is performed within a callback function.

 You are free to use this code for absolutely anything except starting a nuclear holocaust. 
 I offer no warranty that this code will (a) work (b) do bad things to your computer.

 Compile with something like:
 mpicc hello_world_mpi3.c `gtk-config --cflags --libs`

 Run with something like:
 mpirun -v -np 4 ./a.out

 ******************************************************/

#include <stdio.h>
#include <unistd.h>
#include <mpi.h>
#include <gtk/gtk.h>

#define STR_LEN 20

/* Nasty global variables */
int rank, size;

void slave_function(void)
  {
  char msg[STR_LEN];
  MPI_Status status;

  do
    {
    MPI_Recv(msg, STR_LEN, MPI_CHAR, 0, 99, MPI_COMM_WORLD, &status);
    printf("Node %d/%d received message, \"%s\"\n", rank, size, msg);
    } while(strcmp(msg,"quit")!=0);

  return;
  }


void quit_callback(GtkWidget *widget, gpointer data)
  {
  gtk_main_quit();

  return;
  }


void send_callback(GtkWidget *widget, gpointer data)
  {
  char msg[STR_LEN];
  MPI_Status status;
  int     i;

  strcpy(msg,"Hello World!");

  printf("Node %d/%d sending message, \"%s\".\n", rank, size, msg);
  for (i=1; i<size; i++) MPI_Send(msg, STR_LEN, MPI_CHAR, i, 99, MPI_COMM_WORLD);

  return;
  }


void master_function(int *argc, char ***argv)
  {
  GtkWidget *window;
  GtkWidget *label;
  GtkWidget *button_send;
  GtkWidget *button_quit;
  char msg[STR_LEN];
  MPI_Status status;
  int     i;

  gtk_init(argc, argv);

/* Master setup here. */
  window = gtk_dialog_new();
  gtk_window_set_title(GTK_WINDOW(window), "MPI and gtk+: Example 1");
  label = gtk_label_new("Here we use MPI calls in the main code block.\n"
                        "This is version probably most useful when your\n"
                        "GUI is used to control a parallel calculation.");
  gtk_misc_set_padding(GTK_MISC(label), 2, 2);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox),
                        label, TRUE, TRUE, 0);

  button_send = gtk_button_new_with_label("Send");
  gtk_signal_connect(GTK_OBJECT(button_send), "clicked",
                      GTK_SIGNAL_FUNC(send_callback),
                      NULL);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area),
                        button_send, TRUE, TRUE, 0);

  button_quit = gtk_button_new_with_label("Quit");
  gtk_signal_connect(GTK_OBJECT(button_quit), "clicked",
                      GTK_SIGNAL_FUNC(quit_callback),
                      NULL);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area),
                        button_quit, TRUE, TRUE, 0);

  GTK_WIDGET_SET_FLAGS(button_send, GTK_CAN_DEFAULT);
  gtk_widget_grab_default(button_send);

  gtk_widget_show(label);
  gtk_widget_show(button_send);
  gtk_widget_show(button_quit);
  gtk_widget_show(window);

  gtk_main();

/* Master clean-up here. */
  strcpy(msg,"quit");
  printf("Node %d/%d sending message, \"%s\".\n", rank, size, msg);
  for (i=1; i<size; i++) MPI_Send(msg, STR_LEN, MPI_CHAR, i, 99, MPI_COMM_WORLD);

  return;
  }

int main(int argc, char **argv)
  {
  
  MPI_Init(&argc, &argv);
  
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);

/* Global setup here. */
  
  if (rank==0)
    master_function(&argc, &argv);
  else
    slave_function();

/* Global clean-up here. */

  MPI_Finalize();
  }


/******************************************************
 Stewart Adcock, 3 Feb 2002

 Example where all MPI communication is performed in main code block.

 You are free to use this code for absolutely anything except starting a nuclear holocaust.
 I offer no warranty that this code will (a) work (b) do bad things to your computer.

 Compile with something like:
 mpicc hello_world_mpi3.c `gtk-config --cflags --libs`

 Run with something like:
 mpirun -v -np 4 ./a.out

 ******************************************************/

#include <stdio.h>
#include <unistd.h>
#include <mpi.h>
#include <gtk/gtk.h>

#define STR_LEN 20

/* Nasty global variables */
int rank, size;
int quit=0;

void slave_function(void)
  {
  char msg[STR_LEN];
  MPI_Status status;

  do
    {
    MPI_Recv(msg, STR_LEN, MPI_CHAR, 0, 99, MPI_COMM_WORLD, &status);
    printf("Node %d/%d received message, \"%s\"\n", rank, size, msg);
    } while(strcmp(msg,"quit")!=0);

  return;
  }


void quit_callback(GtkWidget *widget, gpointer data)
  {
  quit = 1;

  return;
  }

void master_function(int *argc, char ***argv)
  {
  char msg[STR_LEN];
  GtkWidget *window;
  GtkWidget *label;
  GtkWidget *button;
  MPI_Status status;
  int     i;

  gtk_init(argc, argv);

/* Master setup here. */
  window = gtk_dialog_new();
  gtk_window_set_title(GTK_WINDOW(window), "MPI and gtk+: Example 1");
  label = gtk_label_new("Here we use MPI calls in the main code block.\n"
                        "This is version probably most useful when your\n"
                        "GUI is used to monitor a parallel calculation.");
  gtk_misc_set_padding(GTK_MISC(label), 2, 2);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox),
                        label, TRUE, TRUE, 0);

  button = gtk_button_new_with_label("I've seen enough now");
  gtk_signal_connect(GTK_OBJECT(button), "clicked",
                      GTK_SIGNAL_FUNC(quit_callback),
                      NULL);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->action_area),
                        button, TRUE, TRUE, 0);

  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
  gtk_widget_grab_default(button);

  gtk_widget_show(label);
  gtk_widget_show(button);
  gtk_widget_show(window);

  strcpy(msg,"Hello World!");

/* Main loop here. */
  while (quit==0)
    {
    while (gtk_events_pending())
      gtk_main_iteration();

/* Do stuff here. */
    sleep(1);   /* Just to slow things down! */
    printf("Node %d/%d sending message, \"%s\".\n", rank, size, msg);
    for (i=1; i<size; i++) MPI_Send(msg, STR_LEN, MPI_CHAR, i, 99, MPI_COMM_WORLD);
    }

/* Master clean-up here. */
  strcpy(msg,"quit");
  printf("Node %d/%d sending message, \"%s\".\n", rank, size, msg);
  for (i=1; i<size; i++) MPI_Send(msg, STR_LEN, MPI_CHAR, i, 99, MPI_COMM_WORLD);

  return;
  }

int main(int argc, char **argv)
  {
  
  MPI_Init(&argc, &argv);
  
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);

/* Global setup here. */
  
  if (rank==0)
    master_function(&argc, &argv);
  else
    slave_function();

/* Global clean-up here. */

  MPI_Finalize();
  }




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]