-examples
average_example
+++ /dev/null
-<!--#set var="root_directory" value="../../.." --><!--#include virtual="$root_directory/shared/header.shtml"-->
-
-<h1>Simple Examples</h1>
-
-<h2 id="communication">Communication</h2>
-
-<dl>
- <dt><a href="src/simplest_message.c">simplest_message.c</a></dt>
- <dd>Simplest message passing example — node 0 sends a message
- to other nodes.</dd>
- <dt><a href="src/simple_message.c">simple_message.c</a></dt>
- <dd>Next simplest message passing example — each node (<i>rank
- != 0</i>) sends a message to node 0</dd>
- <dt><a href="src/still_simple.c">still_simple.c</a></dt>
- <dd>Node 0 sends a message to all other nodees. All other nodees
- process the message and send result back to node 0. Nodes form a
- "ring", each node communicating with its neighbors</dd>
- <dt><a href="src/hop.c">hop.c</a></dt>
- <dd>Each node sends a message to right neighbor in a ring. Note:
- The blocking version of the routines produces a deadlock in this
- process.</dd>
- <dt><a href="src/hop_again_again.c">hop_again_again.c</a></dt>
- <dd>Each node sends a message to left and right neighbors in a ring
- fashion again-and-again</dd>
- <dt><a href="src/ring.c">ring.c</a></dt>
- <dd>Non-blocking communication example</dd>
-</dl>
-
-<h2 id="time">Communication time</h2>
-
-<dl>
- <dt><a href="src/ping_pong.c">ping_pong.c</a></dt>
- <dd>Edinburgh example illustrating the scaling of communication
- time.</dd>
-</dl>
-
-<!--#include virtual="$root_directory/shared/footer.shtml"-->
<p>You can measure these communication costs via simple codes that
time the send/receive messages. The
-program <a href="src/ping_pong.c">ping_pong.c</a> (see the Edinburgh
-notes) does precisely this via the <code>MPI_Wtime()</code>
-routines. It sends messages of various length back and forth between
-two processes and measures the round trip times. Running this program
-produces the following figures.</p>
+program <a href="../../src/MPI2_message_passing/ping_pong.c">ping_pong.c</a>
+(see the Edinburgh notes) does precisely this via
+the <code>MPI_Wtime()</code> routines. It sends messages of various
+length back and forth between two processes and measures the round
+trip times. Running this program produces the following figures.</p>
<img border="0" src="img/Message_Time_Rates_1.png" width="384" height="372" />
<img border="0" src="img/Message_Time_Rates_2.png" width="372" height="368" />
<p>Read the code, understand it, and run it to reproduce the figures
above.</p>
+<h2 id="examples">Simple Examples</h2>
+
+The following message passing examples are bundled in
+<a href="../../src/MPI2_message_passing/MPI2_message_passing.tar.gz">MPI2_message_passing.tar.gz</a>.
+
+<h3 id="communication">Communication</h3>
+
+<dl>
+ <dt><a href="../../src/MPI2_message_passing/simplest_message.c">simplest_message.c</a></dt>
+ <dd>Simplest message passing example — node 0 sends a message
+ to other nodes.</dd>
+ <dt><a href="../../src/MPI2_message_passing/simple_message.c">simple_message.c</a></dt>
+ <dd>Next simplest message passing example — each node (<i>rank
+ != 0</i>) sends a message to node 0</dd>
+ <dt><a href="../../src/MPI2_message_passing/still_simple.c">still_simple.c</a></dt>
+ <dd>Node 0 sends a message to all other nodes. All other nodes
+ process the message and send result back to node 0. Nodes form a
+ "ring", each node communicating with its neighbors</dd>
+ <dt><a href="../../src/MPI2_message_passing/hop.c">hop.c</a></dt>
+ <dd>Each node sends a message to right neighbor in a ring. Note:
+ The blocking version of the routines produces a deadlock in this
+ process.</dd>
+ <dt><a href="../../src/MPI2_message_passing/hop_again_again.c">hop_again_again.c</a></dt>
+ <dd>Each node sends a message to left and right neighbors in a ring
+ fashion again-and-again</dd>
+ <dt><a href="../../src/MPI2_message_passing/ring.c">ring.c</a></dt>
+ <dd>Non-blocking communication example</dd>
+</dl>
+
+<h3 id="time">Communication time</h3>
+
+<dl>
+ <dt><a href="../../src/MPI2_message_passing/ping_pong.c">ping_pong.c</a></dt>
+ <dd>Edinburgh example illustrating the scaling of communication
+ time.</dd>
+</dl>
+
<!--#include virtual="$root_directory/shared/footer.shtml"-->
--- /dev/null
+# Environment
+
+CC = /usr/bin/mpicc
+CFLAGS =
+LD = $(CC)
+LDFLAGS =
+RM = /bin/rm
+EXECS = simplest_message simple_message still_simple hop \
+ hop_again_again ring ping_pong
+
+all: $(EXECS)
+
+%.o : %.c
+ $(CC) -c $(CFLAGS) -o $@ $^
+
+$(EXECS) : % : %.o
+ $(LD) $(LDFLAGS) -o $@ $^
+
+clean:
+ $(RM) -f *.o $(EXECS)
+
+# Interesting Makefile sections
+# 4.12.1 Syntax of Static Pattern Rules
--- /dev/null
+MPI2_message_passing
+====================
+
+Simple demonstrations of message passing in MPI.
+
+Manifest
+--------
+
+Administrative
+~~~~~~~~~~~~~~
+
+- README
+ This file.
+- Makefile
+ Automate building and cleanup.
+
+Communication
+~~~~~~~~~~~~~
+
+- simplest_message.c
+ Simplest message passing example - node 0 sends a message to other nodes.
+- simple_message.c
+ Next simplest message passing example - each node (rank != 0)
+ sends a message to node 0.
+- still_simple.c
+ Node 0 sends a message to all other nodees. All other nodees
+ process the message and send result back to node 0. Nodes form a
+ "ring", each node communicating with its neighbors.
+- hop.c
+ Each node sends a message to right neighbor in a ring. Note: The
+ blocking version of the routines produces a deadlock in this process.
+- hop_again_again.c
+ Each node sends a message to left and right neighbors in a ring
+ fashion again-and-again.
+- ring.c
+ Non-blocking communication example.
+
+Communication time
+~~~~~~~~~~~~~~~~~~
+- ping_pong.c
+ Edinburgh example illustrating the scaling of communication time.
+
+Build
+-----
+
+Just run
+
+ $ make
+
+Usage
+-----
+
+MPI configuration
+~~~~~~~~~~~~~~~~~
+
+You should only have to do this once for each host, but since this is
+your first MPI program, you probably haven't done it yet. From
+
+ $ man mpd
+
+we have:
+
+ "A file named .mpd.conf file must be present in the user's home
+ directory with read and write access only for the user, and must
+ contain at least a line with MPD_SECRETWORD=<secretword>"
+
+so create the file with a random secret word:
+
+ $ touch ~/.mpd.conf
+ $ chmod 600 ~/.mpd.conf
+ $ echo "MPD_SECRETWORD=$(cat /dev/urandom | tr -d -c A-Z-a-z-0-9 | head -c 60)" ~/.mpd.conf
+
+Running MPI programs
+~~~~~~~~~~~~~~~~~~~~
+
+Create a list of possible hosts `mpd.hosts`, for example
+
+ xphy1.physics.xterm.net
+ xphy2.physics.xterm.net
+ ...
+
+Start the Message Passing Daemons with
+
+ $ mpdboot -f mpd.hosts
+
+which spawns a daemon (`mpd`) on each host. Then run your program
+(e.g. `simplest_message`) with.
+
+ $ mpiexec -n 4 ./simplest_message
+
+When you're done, clean up the daemons with
+
+ $ mpdallexit
+
+Examples for each of the executables in this package:
+
+ $ mpiexec -n 4 ./simplest_message
+ $ mpiexec -n 4 ./simple_message
+ $ mpiexec -n 4 ./still_simple
+ $ mpiexec -n 4 ./hop
+ $ mpiexec -n 4 ./hop_again_again
+ $ mpiexec -n 4 ./ring
+ $ mpiexec -n 4 ./ping_pong
-
- /* node identifications */
+/* passing messages to neighbors */
- /* passing a message to neighbors */
- /* Michel Vallieres */
-#include <stdio.h>
-#include <mpi.h>
+/* Michel Vallieres */
+
+#include <stdio.h>
+#include <mpi.h>
int main (int argc, char *argv[])
{
-int my_rank, size;
-MPI_Status recv_status;
-int my_number, hop;
-int target_node, from_node;
-int message;
-
- MPI_Init(&argc, &argv);
-
- MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
- MPI_Comm_size(MPI_COMM_WORLD, &size);
-
- /* def my_number */
- my_number = 2 * my_rank;
- /* define hop */
- hop = 1 ;
- /* target node */
- target_node = my_rank + hop;
- target_node = target_node % size;
- /* from node */
- from_node = my_rank- hop;
- from_node = (from_node + size) % size;
- /* Print out a message from each processor */
- fprintf( stderr,
- "This is process %d out of %d -- target & from: %d %d -- my number %d\n",
- my_rank, size, target_node, from_node, my_number );
-
- /* send info to target node */
- /* */
- /* note: a blocking send */
- /* MPI_Ssend produces a */
- /* deadlock in this case */
- message = my_number;
- MPI_Ssend(&message, 1, MPI_INT, target_node, 121, MPI_COMM_WORLD);
-
- /* receive new number from the */
- /* - from node - */
- MPI_Recv(&message, 1, MPI_INT, from_node, 121,
- MPI_COMM_WORLD, &recv_status);
- /* update my_number */
- my_number = message;
-
- printf ( " I am process %d -- my number is now : %d \n",
- my_rank, my_number );
-
- MPI_Finalize();
+ int rank, size;
+ int number, hop;
+ int target_node, from_node, count, tag;
+ int message;
+ MPI_Status recv_status;
+
+ MPI_Init(&argc, &argv);
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ MPI_Comm_size(MPI_COMM_WORLD, &size);
+
+ count = 1; /* only sending a single MPI_INT */
+ tag = 123; /* arbitrary integer tagging the message */
+
+ number = 2 * rank; /* pick a number to pass */
+ hop = 1 ; /* define hop, from [0,size) */
+ target_node = (rank + hop) % size; /* target node */
+ from_node = (rank - hop + size) % size; /* from node */
+ /* The '+ size' in the from_node calculation ensures a positive from_node. */
+
+ /* Print out a message from each processor */
+ printf("This is process %d out of %d -- target %d, from %d, number %d\n",
+ rank, size, target_node, from_node, number);
+
+ /* Send info to target node. Note: a blocking send MPI_Ssend
+ * produces a deadlock in this case. */
+ message = number;
+ MPI_Send(&message, count, MPI_INT, target_node, tag, MPI_COMM_WORLD);
+
+ /* Receive new number from the from node. */
+ MPI_Recv(&message, count, MPI_INT, from_node, tag,
+ MPI_COMM_WORLD, &recv_status);
+ number = message; /* update number */
+
+ printf ("I am process %d -- my number is now %d\n", rank, number);
+
+ MPI_Finalize();
}
-
-
-
- /* node identifications */
+/* passing a message to neighbors, multiple hops */
- /* passing a message to neighbors */
- /* multiple hops */
- /* Michel Vallieres */
-#include <stdio.h>
-#include <mpi.h>
+/* Michel Vallieres */
-void permute ( int hop, int *my_number, int my_rank, int size )
+#include <stdio.h>
+#include <mpi.h>
+
+void permute (int hop, int *number, int rank, int size)
{
-MPI_Status recv_status;
-int target_node, from_node;
-int message;
- /* target node */
- target_node = my_rank + hop;
- target_node = (target_node +size) % size;
- /* from node */
- from_node = my_rank- hop;
- from_node = (from_node + size) % size;
- /* send info to target node */
- /* */
- /* note: a blocking send */
- /* MPI_Ssend will node lock */
- /* in this case */
- message = *my_number;
- MPI_Send(&message, 1, MPI_INT, target_node, 121, MPI_COMM_WORLD);
- /* receive new number from the */
- /* - from node - */
- MPI_Recv(&message, 1, MPI_INT, from_node, 121,
- MPI_COMM_WORLD, &recv_status);
- /* update my_number */
- *my_number = message;
+ MPI_Status recv_status;
+ int target_node, from_node, count, tag;
+ int message;
+
+ count = 1; /* only sending a single MPI_INT */
+ tag = 123; /* arbitrary integer tagging the message */
+
+ target_node = (rank + hop + size) % size; /* target node */
+ from_node = (rank - hop + size) % size; /* from node */
+ /* The '+ size' ensures positive nodes for hops in the range (-size,size). */
+
+ /* Send info to target node. Note: a blocking send MPI_Ssend
+ * produces a deadlock in this case. */
+ message = *number;
+ MPI_Send(&message, count, MPI_INT, target_node, tag, MPI_COMM_WORLD);
+
+ /* Receive new number from the from node. */
+ MPI_Recv(&message, count, MPI_INT, from_node, tag,
+ MPI_COMM_WORLD, &recv_status);
+ *number = message; /* update number */
}
-
int main (int argc, char *argv[])
{
-int my_rank, size;
-MPI_Status recv_status;
-int my_number, hop;
-int target_node, from_node;
-int message;
+ int rank, size;
+ int number, hop;
- MPI_Init(&argc, &argv);
+ MPI_Init(&argc, &argv);
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ MPI_Comm_size(MPI_COMM_WORLD, &size);
- MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
- MPI_Comm_size(MPI_COMM_WORLD, &size);
+ number = 2 * rank; /* pick a number to pass */
- /* def my_number */
- my_number = 2 * my_rank;
-
- printf ( " I am process %d -- my number is : %d \n",
- my_rank, my_number );
+ printf ("0: I am process %d -- my number is %d\n", rank, number);
- /* first hop */
- hop = 1;
- permute( hop, &my_number, my_rank, size );
- printf ( " I am process %d -- my number is : %d \n",
- my_rank, my_number );
- /* second hop */
- hop = -2;
- permute( hop, &my_number, my_rank, size );
- printf ( " I am process %d -- my number is : %d \n",
- my_rank, my_number );
- /* third hop */
- hop = 1;
- permute( hop, &my_number, my_rank, size );
- printf ( " I am process %d -- my number is : %d \n",
- my_rank, my_number );
+ /* first hop */
+ hop = 1;
+ permute(hop, &number, rank, size);
+ printf("1: I am process %d -- my number is %d\n", rank, number);
- MPI_Finalize();
-}
+ /* second hop */
+ hop = -2;
+ permute(hop, &number, rank, size);
+ printf("2: I am process %d -- my number is %d\n", rank, number);
-
+ /* third hop */
+ hop = 1;
+ permute(hop, &number, rank, size);
+ printf("3: I am process %d -- my number is %d \n", rank, number);
+
+ MPI_Finalize();
+}
-
/************************************************************************
- * This file has been written as a sample solution to an exercise in a
+ * This file has been written as a sample solution to an exercise in a
* course given at the Edinburgh Parallel Computing Centre. It is made
* freely available with the understanding that every copy of this file
* must include this header and that EPCC takes no responsibility for
* Contact: epcc-tec@epcc.ed.ac.uk
*
* Purpose: A program to experiment with point-to-point
- * communications.
+ * communications.
*
* Contents: C source code.
*
************************************************************************/
-#include <stdio.h>
-#include <mpi.h>
-
-#define proc_A 0
-#define proc_B 1
-#define ping 101
-#define pong 101
+#include <stdio.h>
+#include <mpi.h>
-float buffer[100000];
+#define PROCESS_A 0 /* node sending the first ping */
+#define PROCESS_B 1 /* nore receiving the first ping */
+#define TAG_PING 100 /* A -> B messages */
+#define TAG_PONG 101 /* B -> A messages */
+#define BUF_SIZE 100000 /* size of the buffer holding the messages */
+#define MAX_LENGTH 30000 /* maximum message size (must be <= BUF_SIZE */
+#define MIN_LENGTH 1 /* minimum message size */
+#define LENGTH_INCREMENT 1000 /* increase in message size between messages */
+#define NUM_MSGS 100 /* number of messages to pass for each size */
-void processor_A (void);
-void processor_B (void);
+void processor_A(void);
+void processor_B(void);
-int main ( int argc, char *argv[] )
+int main (int argc, char *argv[])
{
- int ierror, rank, size;
-
- MPI_Init(&argc, &argv);
+ int ierror, rank, size;
- MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ MPI_Init(&argc, &argv);
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
- if (rank == proc_A) processor_A();
- else if (rank == proc_B) processor_B();
+ if (rank == PROCESS_A) processor_A();
+ else if (rank == PROCESS_B) processor_B();
+ /* other ranks fall through and die silently */
- MPI_Finalize();
+ MPI_Finalize();
}
-
-void processor_A( void )
+void processor_A(void)
{
- int i, ierror;
- MPI_Status status;
-
- double start, finish, time;
-
- extern float buffer[100000];
+ int i, ierror;
+ MPI_Status status;
+ double start, finish, time;
+ float buffer[BUF_SIZE];
+ int length;
- int length;
+ printf("length\ttime per message (s)\ttransfer rate (kB/s)\n");
- printf("Length\tTotal Time\tTransfer Rate\n");
+ for (length = MIN_LENGTH; length <= MAX_LENGTH; length += LENGTH_INCREMENT)
+ {
+ start = MPI_Wtime();
- for (length = 1; length <= 30000; length += 1000)
- {
- start = MPI_Wtime();
-
- for (i = 1; i <= 100; i++)
+ for (i=0; i < NUM_MSGS; i++)
{
- MPI_Ssend(buffer, length, MPI_FLOAT, proc_B, ping,
- MPI_COMM_WORLD);
+ MPI_Ssend(buffer, length, MPI_FLOAT, PROCESS_B, TAG_PING,
+ MPI_COMM_WORLD);
- MPI_Recv(buffer, length, MPI_FLOAT, proc_B, pong,
- MPI_COMM_WORLD, &status);
+ MPI_Recv(buffer, length, MPI_FLOAT, PROCESS_B, TAG_PONG,
+ MPI_COMM_WORLD, &status);
}
- finish = MPI_Wtime();
- time = finish - start;
+ finish = MPI_Wtime();
+ time = finish - start;
- printf("%d\t%f\t%f\n", length, time/200.,
- (float)(2 * 8 * 100 * length)/time);
+ printf("%d\t%f\t%f\n",
+ length,
+ (float) time / (2 * NUM_MSGS),
+ (2 * NUM_MSGS * sizeof(float) * length) / (1e3 * time));
+ /* 2 to count ping and pong */
}
}
void processor_B( void )
{
- int i, ierror;
- MPI_Status status;
- extern float buffer[100000];
- int length;
-
- for (length = 1; length <= 30000; length += 1000)
- {
- for (i = 1; i <= 100; i++)
- {
- MPI_Recv(buffer, length, MPI_FLOAT, proc_A, ping,
- MPI_COMM_WORLD, &status);
-
- MPI_Ssend(buffer, length, MPI_FLOAT, proc_A, pong,
- MPI_COMM_WORLD);
- }
+ int i, ierror;
+ MPI_Status status;
+ float buffer[BUF_SIZE];
+ int length;
+
+ for (length = MIN_LENGTH; length <= MAX_LENGTH; length += LENGTH_INCREMENT)
+ {
+ for (i=0; i < NUM_MSGS; i++)
+ {
+ MPI_Recv(buffer, length, MPI_FLOAT, PROCESS_A, TAG_PING,
+ MPI_COMM_WORLD, &status);
+
+ MPI_Ssend(buffer, length, MPI_FLOAT, PROCESS_A, TAG_PONG,
+ MPI_COMM_WORLD);
+ }
}
}
-
-
-
-
-
/************************************************************************
- * This file has been written as a sample solution to an exercise in a
+ * This file has been written as a sample solution to an exercise in a
* course given at the Edinburgh Parallel Computing Centre. It is made
* freely available with the understanding that every copy of this file
* must include this header and that EPCC takes no responsibility for
* the use of the enclosed teaching material.
*
- * Author: Joel Malard
+ * Author: Joel Malard
*
* Contact: epcc-tec@epcc.ed.ac.uk
*
- * Purpose: A program to try out non-blocking point-to-point
+ * Purpose: A program to try out non-blocking point-to-point
* communications.
*
* Contents: C source code.
*
************************************************************************/
-#include <stdio.h>
-#include <mpi.h>
-#define tag_right 201
-#define tag_left 102
+#include <stdio.h>
+#include <mpi.h>
+
+#define TAG_RIGHT 123
int main (int argc, char *argv[])
{
-int ierror, rank, my_rank, size;
-int right, left;
-int other, sum, i;
-int message;
+ int ierror, rank, size;
+ int right, left, count, i;
+ int message, sum;
-MPI_Status send_status;
-MPI_Status recv_status;
-MPI_Request request;
+ MPI_Status send_status;
+ MPI_Status recv_status;
+ MPI_Request request;
- MPI_Init(&argc, &argv);
+ MPI_Init(&argc, &argv);
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ MPI_Comm_size(MPI_COMM_WORLD, &size);
- MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
- MPI_Comm_size(MPI_COMM_WORLD, &size);
+ count = 1; /* only sending a single MPI_INT */
+ right = (rank + 1) % size;
+ left = (rank - 1 + size) % size; /* the '+ size' ensures 'left >= 0'. */
- right = my_rank + 1;
- if (right == size) right = 0;
+ sum = 0;
+ message = rank;
- left = my_rank - 1;
- if (left == -1) left = size-1;
+ for (i=0; i < size; i++) {
+ /* Issend because? */
+ MPI_Issend(&message, count, MPI_INT, right, TAG_RIGHT,
+ MPI_COMM_WORLD, &request);
- sum = 0;
- message = my_rank;
+ MPI_Recv(&message, count, MPI_INT, left, TAG_RIGHT,
+ MPI_COMM_WORLD, &recv_status);
- for( i = 0; i < size; i++) {
+ /* Wait because? */
+ MPI_Wait(&request, &send_status);
- MPI_Issend(&message, 1, MPI_INT, right, tag_right,
- MPI_COMM_WORLD, &request);
-
- MPI_Recv(&other, 1, MPI_INT, left, tag_right,
- MPI_COMM_WORLD, &recv_status);
-
- MPI_Wait(&request, &send_status);
-
- sum = sum + other;
- message = other;
-
- }
+ sum += message;
+ }
- printf ("PE%d:\tSum = %d\n", my_rank, sum);
-
- MPI_Finalize();
+ printf ("PE%d:\tSum = %d\n", rank, sum);
+ MPI_Finalize();
}
-
+/* Simplest code to illustrate Message Passing */
+/* Nodes 1 to size-1 send messages to node 0. */
- /* Simplest code to illustrate */
- /* Message Passing */
+/* Michel Vallieres */
- /* nodes 1 to size-1 send message to node 0 */
-
- /* Michel Vallieres */
-#include <stdio.h>
-#include <mpi.h>
+#include <stdio.h>
+#include <mpi.h>
int main (int argc, char *argv[])
{
-int my_rank, size;
-int err, process, send_mesg, recv_mesg;
-
-MPI_Status recv_status;
+ int rank, size;
+ int err, process, source, count, tag, send_mesg, recv_mesg;
+ MPI_Status recv_status;
- MPI_Init(&argc, &argv);
+ MPI_Init(&argc, &argv);
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ MPI_Comm_size(MPI_COMM_WORLD, &size);
- MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
- MPI_Comm_size(MPI_COMM_WORLD, &size);
+ count = 1; /* only sending a single MPI_INT */
+ tag = 123; /* arbitrary integer tagging the message */
- if ( my_rank == 0 )
- {
- for ( process=1; process<size; process++)
+ if (rank == 0)
+ {
+ for (process=1; process < size; process++)
{
- err = MPI_Recv(&recv_mesg, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG,
- MPI_COMM_WORLD, &recv_status);
- printf("Received message %d from node %d \n",
- recv_mesg, recv_status.MPI_SOURCE );
- printf("err %d, ( byte count, tag, and error code were: %d %d %d ) \n",
- err, recv_status.count,recv_status.MPI_TAG,
- recv_status.MPI_ERROR );
+ err = MPI_Recv(&recv_mesg, count, MPI_INT, MPI_ANY_SOURCE,
+ MPI_ANY_TAG, MPI_COMM_WORLD, &recv_status);
+ printf("Received message %d from node %d\n",
+ recv_mesg, recv_status.MPI_SOURCE);
+ printf(" (byte count %d, tag %d, error code %d)\n",
+ recv_status.count, recv_status.MPI_TAG, err);
}
- }
- else
- {
- send_mesg=2*my_rank;
- MPI_Ssend(&send_mesg, 1, MPI_INT, 0, 121, MPI_COMM_WORLD);
- }
-
-
+ }
+ else
+ {
+ process = 0; /* send to node 0 */
+ send_mesg = 2*rank;
+ MPI_Ssend(&send_mesg, count, MPI_INT, process, tag, MPI_COMM_WORLD);
+ }
+
MPI_Finalize();
}
- /* Simplest code to illustrate */
- /* Message Passing */
+/* Simplest code to illustrate Message Passing */
+/* Node 0 sends message to other nodes. */
- /* nodes 0 sends message to other nodes */
+/* Michel Vallieres */
- /* Michel Vallieres */
-#include <stdio.h>
-#include <mpi.h>
+#include <stdio.h>
+#include <mpi.h>
int main (int argc, char *argv[])
{
-int my_rank, size;
-int err, process, send_mesg, recv_mesg;
+ int rank, size;
+ int err, process, source, count, tag, send_mesg, recv_mesg;
+ MPI_Status recv_status;
-MPI_Status recv_status;
+ MPI_Init(&argc, &argv);
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ MPI_Comm_size(MPI_COMM_WORLD, &size);
- MPI_Init(&argc, &argv);
+ count = 1; /* only sending a single MPI_INT */
+ tag = 123; /* arbitrary integer tagging the message */
- MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
- MPI_Comm_size(MPI_COMM_WORLD, &size);
-
- if ( my_rank == 0 )
- {
- for ( process=1; process<size; process++)
- {
- send_mesg=2*process;
- err = MPI_Ssend(&send_mesg, 1, MPI_INT, process, 125, MPI_COMM_WORLD );
+ if (rank == 0)
+ {
+ for (process=1; process < size; process++)
+ {
+ send_mesg=2*process;
+ err = MPI_Ssend(&send_mesg, count, MPI_INT, process, tag,
+ MPI_COMM_WORLD);
}
- }
- else
- {
- err = MPI_Recv(&recv_mesg, 1, MPI_INT, 0, MPI_ANY_TAG,
- MPI_COMM_WORLD, &recv_status);
- printf( "Node %d received message %d (error %d) \n", my_rank, recv_mesg, err );
- }
-
-
- MPI_Finalize();
+ }
+ else
+ {
+ source = 0; /* receive from node 0 */
+ err = MPI_Recv(&recv_mesg, count, MPI_INT, source, MPI_ANY_TAG,
+ MPI_COMM_WORLD, &recv_status);
+ printf("Node %d received message %d (error %d)\n",
+ rank, recv_mesg, err );
+ }
+
+ MPI_Finalize();
}
+/* Simple code to illustrate Message Passing */
- /* Simplest code to illustrate */
- /* Message Passing */
+/* Node 0 sends a message to all other processes, other nodes process
+ * info and send result back to node 0.
+ *
+ * The trivial operation the nodes preform is to divide a number
+ * (selected by the main program) by their own rank number.
+ */
- /* process 0 sends a message to */
- /* all other processes */
- /* other processes process info */
- /* send result back to process 0 */
+/* Michel Vallieres */
- /* trivial operation to perfom is to divide*/
- /* a number (selected by the main program) */
- /* by the rank number of the process */
-
- /* Michel Vallieres */
-#include <stdio.h>
-#include <mpi.h>
+#include <stdio.h>
+#include <mpi.h>
int main (int argc, char *argv[])
{
-int my_rank, size;
-int process;
-double number, send_mesg, recv_mesg;
-
-MPI_Status recv_status;
+ int rank, size, err;
+ int process, source, count, tag;
+ double number, send_mesg, recv_mesg;
+ MPI_Status recv_status;
- MPI_Init(&argc, &argv);
+ MPI_Init(&argc, &argv);
+ MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+ MPI_Comm_size(MPI_COMM_WORLD, &size);
- MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
- MPI_Comm_size(MPI_COMM_WORLD, &size);
+ count = 1; /* only sending a single MPI_INT */
+ tag = 123; /* arbitrary integer tagging the message */
- if ( my_rank == 0 )
- {
- number = 5.167321; /* arbitrary number */
- /* send number to other nodes */
- for ( process=1; process<size; process++)
+ if (rank == 0)
+ {
+ number = 5.167321; /* arbitrary number */
+ for (process=1; process < size; process++)
{
- MPI_Ssend(&number, 1, MPI_DOUBLE, process, 121, MPI_COMM_WORLD);
+ /* send number to other nodes */
+ MPI_Ssend(&number, count, MPI_DOUBLE, process, tag, MPI_COMM_WORLD);
}
- /* then receive results */
- for ( process=1; process<size; process++)
- {
- MPI_Recv(&recv_mesg, 1, MPI_DOUBLE, MPI_ANY_SOURCE, 99,
- MPI_COMM_WORLD, &recv_status);
- printf("Received message %f from node %d \n",
- recv_mesg, recv_status.MPI_SOURCE );
- printf(" ( byte count, tag, and error code were: %d %d %d ) \n",
- recv_status.count,recv_status.MPI_TAG,
- recv_status.MPI_ERROR );
+ for (process=1; process < size; process++)
+ {
+ /* receive results */
+ err = MPI_Recv(&recv_mesg, count, MPI_DOUBLE, MPI_ANY_SOURCE, tag,
+ MPI_COMM_WORLD, &recv_status);
+ printf("Received message %f from node %d\n",
+ recv_mesg, recv_status.MPI_SOURCE );
+ printf(" (byte count %d, tag %d, error code %d)\n",
+ recv_status.count,recv_status.MPI_TAG, err);
+ /* Note that we do not use recv_status.MPI_ERROR.
+ * From the MPICH2 Manual, Section 47. Return Status:
+ * http://www.mpi-forum.org/docs/mpi22-report/node47.htm#Node47
+ * "In general, message-passing calls do not modify the
+ * value of the error code field of status variables. This
+ * field may be updated only by the functions in Section
+ * Multiple Completions which return multiple
+ * statuses. The field is updated if and only if such
+ * function returns with an error code of
+ * MPI_ERR_IN_STATUS."
+ */
}
- }
- else
- {
- /* receives message from master */
- MPI_Recv(&recv_mesg, 1, MPI_DOUBLE, 0, 121,
- MPI_COMM_WORLD, &recv_status);
- /* processes info */
- send_mesg=recv_mesg/my_rank;
- /* sends results back to master */
- MPI_Ssend(&send_mesg, 1, MPI_DOUBLE, 0, 99, MPI_COMM_WORLD);
- }
-
-
- MPI_Finalize();
+ }
+ else
+ {
+ process = 0; /* communicate with node 0 */
+ /* recieve information */
+ MPI_Recv(&recv_mesg, count, MPI_DOUBLE, process, tag,
+ MPI_COMM_WORLD, &recv_status);
+ /* processes information */
+ send_mesg=recv_mesg/rank;
+ /* sends results back */
+ MPI_Ssend(&send_mesg, count, MPI_DOUBLE, process, tag, MPI_COMM_WORLD);
+ }
+
+ MPI_Finalize();
}
which spawns a daemon (`mpd`) on each host. Then run your program
(e.g. `hello`) with.
- $ mpiexec -l -n 1 ./hello
+ $ mpiexec -n 1 ./hello
Note that we use ./hello instead of hello or you'll get errors like