Hi,
I have two versions of a small program. In the first one the process with rank 0
calls the function "master()" and all other ranks call the function "slave()"
and in the second one I have two programs: one for the master task and another
one for the slave task. The run-time for the second version is much bigger than
the one for the first version. Any ideas why the version with two separate
programs takes that long?
loki tmp 108 mpicc -o hello_1_mpi hello_1_mpi.c
loki tmp 109 mpicc -o hello_2_mpi hello_2_mpi.c
loki tmp 110 mpicc -o hello_2_slave_mpi hello_2_slave_mpi.c
loki tmp 111 /usr/bin/time -p mpiexec -np 3 hello_1_mpi
Process 0 of 3 running on loki
Process 1 of 3 running on loki
Process 2 of 3 running on loki
...
real 0.14
user 0.00
sys 0.00
loki tmp 112 /usr/bin/time -p mpiexec -np 1 hello_2_mpi : \
-np 2 hello_2_slave_mpi
Process 0 of 3 running on loki
Process 1 of 3 running on loki
Process 2 of 3 running on loki
...
real 23.15
user 0.00
sys 0.00
loki tmp 113 ompi_info | grep "Open MPI repo revision"
Open MPI repo revision: v3.0.0rc2
loki tmp 114
Thank you very much for any answer in advance.
Kind regards
Siegmar
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/utsname.h>
#include "mpi.h"
#define BUF_SIZE 255 /* message buffer size */
#define MAX_TASKS 12 /* max. number of tasks */
#define SENDTAG 1 /* send message command */
#define EXITTAG 2 /* termination command */
#define MSGTAG 3 /* normal message token */
#define ENTASKS -1 /* error: too many tasks */
static void master (void);
static void slave (void);
int main (int argc, char *argv[])
{
int mytid, /* my task id */
ntasks, /* number of parallel tasks */
namelen; /* length of processor name */
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init (&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &mytid);
MPI_Comm_size (MPI_COMM_WORLD, &ntasks);
MPI_Get_processor_name (processor_name, &namelen);
/* With the next statement every process executing this code will
* print one line on the display. It may happen that the lines will
* get mixed up because the display is a critical section. In general
* only one process (mostly the process with rank 0) will print on
* the display and all other processes will send their messages to
* this process. Nevertheless for debugging purposes (or to
* demonstrate that it is possible) it may be useful if every
* process prints itself.
*/
fprintf (stdout, "Process %d of %d running on %s\n",
mytid, ntasks, processor_name);
fflush (stdout);
MPI_Barrier (MPI_COMM_WORLD); /* wait for all other processes */
if (mytid == 0)
{
master ();
}
else
{
slave ();
}
MPI_Finalize ();
return EXIT_SUCCESS;
}
/* Function for the "master task". The master sends a request to all
* slaves asking for a message. After receiving and printing the
* messages he sends all slaves a termination command.
*
* input parameters: not necessary
* output parameters: not available
* return value: nothing
* side effects: no side effects
*
*/
void master (void)
{
int ntasks, /* number of parallel tasks */
mytid, /* my task id */
num, /* number of entries */
i; /* loop variable */
char buf[BUF_SIZE + 1]; /* message buffer (+1 for '\0') */
MPI_Status stat; /* message details */
MPI_Comm_rank (MPI_COMM_WORLD, &mytid);
MPI_Comm_size (MPI_COMM_WORLD, &ntasks);
if (ntasks > MAX_TASKS)
{
fprintf (stderr, "Error: Too many tasks. Try again with at most "
"%d tasks.\n", MAX_TASKS);
/* terminate all slave tasks */
for (i = 1; i < ntasks; ++i)
{
MPI_Send ((char *) NULL, 0, MPI_CHAR, i, EXITTAG, MPI_COMM_WORLD);
}
MPI_Finalize ();
exit (ENTASKS);
}
printf ("\n\nNow %d slave tasks are sending greetings.\n\n",
ntasks - 1);
/* request messages from slave tasks */
for (i = 1; i < ntasks; ++i)
{
MPI_Send ((char *) NULL, 0, MPI_CHAR, i, SENDTAG, MPI_COMM_WORLD);
}
/* wait for messages and print greetings */
for (i = 1; i < ntasks; ++i)
{
MPI_Recv (buf, BUF_SIZE, MPI_CHAR, MPI_ANY_SOURCE,
MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
MPI_Get_count (&stat, MPI_CHAR, &num);
buf[num] = '\0'; /* add missing end-of-string */
printf ("Greetings from task %d:\n"
" message type: %d\n"
" msg length: %d characters\n"
" message: %s\n\n",
stat.MPI_SOURCE, stat.MPI_TAG, num, buf);
}
/* terminate all slave tasks */
for (i = 1; i < ntasks; ++i)
{
MPI_Send ((char *) NULL, 0, MPI_CHAR, i, EXITTAG, MPI_COMM_WORLD);
}
}
/* Function for "slave tasks". The slave task sends its hostname,
* operating system name and release, and processor architecture
* as a message to the master.
*
* input parameters: not necessary
* output parameters: not available
* return value: nothing
* side effects: no side effects
*
*/
void slave (void)
{
struct utsname sys_info; /* system information */
int mytid, /* my task id */
more_to_do;
char buf[BUF_SIZE]; /* message buffer */
MPI_Status stat; /* message details */
MPI_Comm_rank (MPI_COMM_WORLD, &mytid);
more_to_do = 1;
while (more_to_do == 1)
{
/* wait for a message from the master task */
MPI_Recv (buf, BUF_SIZE, MPI_CHAR, 0, MPI_ANY_TAG,
MPI_COMM_WORLD, &stat);
if (stat.MPI_TAG != EXITTAG)
{
uname (&sys_info);
strcpy (buf, "\n hostname: ");
strncpy (buf + strlen (buf), sys_info.nodename,
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), "\n operating system: ",
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), sys_info.sysname,
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), "\n release: ",
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), sys_info.release,
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), "\n processor: ",
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), sys_info.machine,
BUF_SIZE - strlen (buf));
MPI_Send (buf, strlen (buf), MPI_CHAR, stat.MPI_SOURCE,
MSGTAG, MPI_COMM_WORLD);
}
else
{
more_to_do = 0; /* terminate */
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
#define BUF_SIZE 255 /* message buffer size */
#define MAX_TASKS 12 /* max. number of tasks */
#define SENDTAG 1 /* send message command */
#define EXITTAG 2 /* termination command */
#define MSGTAG 3 /* normal message token */
#define ENTASKS -1 /* error: too many tasks */
int main (int argc, char *argv[])
{
int mytid, /* my task id */
ntasks, /* number of parallel tasks */
namelen, /* length of processor name */
num, /* number of chars in buffer */
i; /* loop variable */
char processor_name[MPI_MAX_PROCESSOR_NAME],
buf[BUF_SIZE + 1]; /* message buffer (+1 for '\0') */
MPI_Status stat; /* message details */
MPI_Init (&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &mytid);
MPI_Comm_size (MPI_COMM_WORLD, &ntasks);
MPI_Get_processor_name (processor_name, &namelen);
/* With the next statement every process executing this code will
* print one line on the display. It may happen that the lines will
* get mixed up because the display is a critical section. In general
* only one process (mostly the process with rank 0) will print on
* the display and all other processes will send their messages to
* this process. Nevertheless for debugging purposes (or to
* demonstrate that it is possible) it may be useful if every
* process prints itself.
*/
fprintf (stdout, "Process %d of %d running on %s\n",
mytid, ntasks, processor_name);
fflush (stdout);
MPI_Barrier (MPI_COMM_WORLD); /* wait for all other processes */
if (ntasks > MAX_TASKS)
{
fprintf (stderr, "Error: Too many tasks. Try again with at most "
"%d tasks.\n", MAX_TASKS);
/* terminate all slave tasks */
for (i = 1; i < ntasks; ++i)
{
MPI_Send ((char *) NULL, 0, MPI_CHAR, i, EXITTAG, MPI_COMM_WORLD);
}
MPI_Finalize ();
exit (ENTASKS);
}
printf ("\n\nNow %d slave tasks are sending greetings.\n\n",
ntasks - 1);
/* request messages from slave tasks */
for (i = 1; i < ntasks; ++i)
{
MPI_Send ((char *) NULL, 0, MPI_CHAR, i, SENDTAG, MPI_COMM_WORLD);
}
/* wait for messages and print greetings */
for (i = 1; i < ntasks; ++i)
{
MPI_Recv (buf, BUF_SIZE, MPI_CHAR, MPI_ANY_SOURCE,
MPI_ANY_TAG, MPI_COMM_WORLD, &stat);
MPI_Get_count (&stat, MPI_CHAR, &num);
buf[num] = '\0'; /* add missing end-of-string */
printf ("Greetings from task %d:\n"
" message type: %d\n"
" msg length: %d characters\n"
" message: %s\n\n",
stat.MPI_SOURCE, stat.MPI_TAG, num, buf);
}
/* terminate all slave tasks */
for (i = 1; i < ntasks; ++i)
{
MPI_Send ((char *) NULL, 0, MPI_CHAR, i, EXITTAG, MPI_COMM_WORLD);
}
MPI_Finalize ();
return EXIT_SUCCESS;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/utsname.h>
#include "mpi.h"
#define BUF_SIZE 255 /* message buffer size */
#define MAX_TASKS 12 /* max. number of tasks */
#define MAX_WTIME 30 /* max. waiting time */
#define SENDTAG 1 /* send message command */
#define EXITTAG 2 /* termination command */
#define MSGTAG 3 /* normal message token */
#define ENTASKS -1 /* error: too many tasks */
int main (int argc, char *argv[])
{
struct utsname sys_info; /* system information */
int mytid, /* my task id */
ntasks, /* number of parallel tasks */
namelen, /* length of processor name */
more_to_do;
char processor_name[MPI_MAX_PROCESSOR_NAME],
buf[BUF_SIZE]; /* message buffer */
MPI_Status stat; /* message details */
MPI_Init (&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &mytid);
MPI_Comm_size (MPI_COMM_WORLD, &ntasks);
MPI_Get_processor_name (processor_name, &namelen);
/* With the next statement every process executing this code will
* print one line on the display. It may happen that the lines will
* get mixed up because the display is a critical section. In general
* only one process (mostly the process with rank 0) will print on
* the display and all other processes will send their messages to
* this process. Nevertheless for debugging purposes (or to
* demonstrate that it is possible) it may be useful if every
* process prints itself.
*/
fprintf (stdout, "Process %d of %d running on %s\n",
mytid, ntasks, processor_name);
fflush (stdout);
MPI_Barrier (MPI_COMM_WORLD); /* wait for all other processes */
srand ((unsigned int) time ((time_t *) NULL) * mytid * mytid);
more_to_do = 1;
while (more_to_do == 1)
{
/* wait for a message from the master task */
MPI_Recv (buf, BUF_SIZE, MPI_CHAR, 0, MPI_ANY_TAG,
MPI_COMM_WORLD, &stat);
if (stat.MPI_TAG != EXITTAG)
{
uname (&sys_info);
strcpy (buf, "\n hostname: ");
strncpy (buf + strlen (buf), sys_info.nodename,
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), "\n operating system: ",
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), sys_info.sysname,
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), "\n release: ",
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), sys_info.release,
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), "\n processor: ",
BUF_SIZE - strlen (buf));
strncpy (buf + strlen (buf), sys_info.machine,
BUF_SIZE - strlen (buf));
sleep (rand () % MAX_WTIME);
MPI_Send (buf, strlen (buf), MPI_CHAR, stat.MPI_SOURCE,
MSGTAG, MPI_COMM_WORLD);
}
else
{
more_to_do = 0; /* terminate */
}
}
MPI_Finalize ();
return EXIT_SUCCESS;
}
_______________________________________________
users mailing list
users@lists.open-mpi.org
https://rfd.newmexicoconsortium.org/mailman/listinfo/users