next up previous index
Next: Program life_g.c Up: MPE Graphics Previous: MPE Graphics

Program cxgraphics.c

This program is very, very short. Here is the code.

#include <stdio.h>
#include <stdlib.h>
#include "mpe.h"
#include "mpe_graphics.h"

int main( int argc, char** argv )
{
    MPE_XGraph graph;
    int ierr, mp_size, my_rank;
	MPE_Color my_color;
    char ckey;

    MPI_Init( &argc, &argv );
    MPI_Comm_size( MPI_COMM_WORLD, &mp_size );
    MPI_Comm_rank( MPI_COMM_WORLD, &my_rank );

    ierr = MPE_Open_graphics( &graph, MPI_COMM_WORLD, NULL,
                              -1, -1, 400, 400, 0 );
    if ( ierr != MPE_SUCCESS ) {
        fprintf( stderr, "%d : MPE_Open_graphics() fails\n", my_rank );
        ierr = MPI_Abort( MPI_COMM_WORLD, 1 );
    }
    my_color = (MPE_Color) (my_rank + 1);
    if ( my_rank == 0 )
        ierr = MPE_Draw_string( graph, 187, 205, MPE_BLUE, "Hello" );
    ierr = MPE_Draw_circle( graph, 200, 200, 20+my_rank*5, my_color );
    ierr = MPE_Update( graph );

    if ( my_rank == 0 ) {
        fprintf( stdout, "Hit any key then return to continue  " );
        fscanf( stdin, "%s", &ckey );
        fprintf( stdout, "\n" );
    }
    MPI_Barrier( MPI_COMM_WORLD );

    ierr = MPE_Close_graphics( &graph );

    MPI_Finalize();
    
    return 0;
}
Here is how to link and compile this program:
gustav@bh1 $ mpicc -o cxgraphics cxgraphics.c -lmpe -L/usr/X11R6/lib -lX11 -lm
gustav@bh1 $
In order to run it you must undertake the following steps:
1.
If your variable DISPLAY points to an ssh socket, which is going to be the case if you connected to the AVIDD cluster using slogin -X, redefine DISPLAY to point to your physical display. Use either the IP number or the fully domainized name of the machine from which you have made the connection. Note that the laboratory PCs don't have fully domainized names, so in this case you need to use their IP numbers. To find what they are, use the netstat -rn command in your local Cygwin environment.
2.
On your display machine, e.g., on your PC, issue the command xhost +. This command is a little dangerous, because it opens your X11 display to read/write operations from any other system. The alternative would be to list the names of all AVIDD nodes, and then for each of them issue the command more specific command, e.g., xhost +bc64.uits.indiana.edu.
3.
Now only you should start the MPD, i.e., issue the command mpdboot. If you had MPD running before, you should shut it down with mpdallexit and then restart it.
4.
Finally, with MPD running you can execute the program by simply saying something like
$ mpiexec -n 16 cxgraphics

Now let us have a closer look at the program and see how the MPE graphics routines are used in it.

After the usual initializations:

    MPI_Init( &argc, &argv );
    MPI_Comm_size( MPI_COMM_WORLD, &mp_size );
    MPI_Comm_rank( MPI_COMM_WORLD, &my_rank );
the program opens the X11 window by calling 
ierr = MPE_Open_graphics( &graph, MPI_COMM_WORLD, NULL,
                              -1, -1, 400, 400, 0 );
Because the mode is non-collective various processes may get different returns from the function call. We test the returns in a way that is very reminiscent of the way other MPI errors have been handled:
    if ( ierr != MPE_SUCCESS ) {
        fprintf( stderr, "%d : MPE_Open_graphics() fails\n", my_rank );
        ierr = MPI_Abort( MPI_COMM_WORLD, 1 );
    }
A process  that has failed to access the X11 display and open its portion of the X11 window writes and error message on standard error and aborts, which is going to take the whole MPI program down.

Assuming that this has not happened, the processes define their color:

    my_color = (MPE_Color) (my_rank + 1);
and process of rank zero writes the word "Hello" on the window:
    if ( my_rank == 0 )
        ierr = MPE_Draw_string( graph, 187, 205, MPE_BLUE, "Hello" );

Now each process draws a circle in its own color with the centre at (200,200). This is accomplished by calling

    ierr = MPE_Draw_circle( graph, 200, 200, 20+my_rank*5, my_color );

The next call to 

    ierr = MPE_Update( graph );
simply ensures that all that's been drawn on the graph gets sent to the X11 window that's associated with it.

At this stage the program waits for the user to type something on the console's keyboard. Otherwise the picture would vanish almost instantaneously and we might not have the time enough to admire it:

    if ( my_rank == 0 ) {
        fprintf( stdout, "Hit any key then return to continue  " );
        fscanf( stdin, "%s", &ckey );
        fprintf( stdout, "\n" );
    }
    MPI_Barrier( MPI_COMM_WORLD );
Observe that it is process zero that is in charge of the console - this is always the case in MPICH2 - the other processes wait for it on the barrier. The barrier must be there, because what follows it is
    ierr = MPE_Close_graphics( &graph );
If other processes did not have to wait on the barrier, they would take their portions of the graph down, but, as it happens, they all get to it only after the user has typed something on the keyboard.

The program ends with the usual:

    MPI_Finalize();
    return 0;
}

Now let me introduce officially the synopsis for each of the graphic functions discussed in this section, as well as some other ones to be used in the next section:

int MPE_Open_graphics(MPE_Xgraph *handle, MPI_Comm comm, char *display,
                      int x, int y, int is_collective);
int MPE_Draw_point(MPE_Xgraph handle, int x, int y, MPE_Color color);
int MPE_Draw_line(MPE_Xgraph handle, int x1, int y1, int x2, int y2, 
                  MPE_Color color);
int MPE_Draw_circle(MPE_Xgraph handle, int centerx, int centery, int radius,
                    MPE_Color color);
int MPE_Update(MPE_XGraph handle);
int MPE_Num_colors(MPE_Xgraph handle, int *number_of_colors);
int MPE_Make_color_array(MPE_XGraph handle, int number_of_colors, 
                         MPE_Color array[]);
int MPE_Close_graphics(MPE_XGraph handle);
int MPE_Draw_string(MPE_XGraph handle, int x, int y, MPE_Color, char* string);
                 

The predefined colors can be found on

/N/hpc/mpich2/include/mpe_graphics.c
In our case they are
MPE_WHITE, MPE_BLACK, MPE_RED, MPE_YELLOW, 
MPE_GREEN, MPE_CYAN, MPE_BLUE, MPE_MAGENTA,
MPE_AQUAMARINE, MPE_FORESTGREEN, MPE_ORANGE, 
MPE_MAROON, MPE_BROWN, MPE_PINK, MPE_CORAL, 
MPE_GRAY
                               

Observe that all processes share the graph. Each process can access any pixel on the graph. It is up to the programmer to ensure that they don't step on each other's toes, unless, of course, this is what the programmer wants.


next up previous index
Next: Program life_g.c Up: MPE Graphics Previous: MPE Graphics
Zdzislaw Meglicki
2004-04-29