Skip to content
Snippets Groups Projects
Commit a1038a3a authored by Chao Zhan's avatar Chao Zhan
Browse files

add manager-worker example

parent c1b5d756
Branches
No related tags found
No related merge requests found
PROG1 = manager
PROG2 = worker
OBJECTS = manager.o worker.o
CC = mpicc
CFLAGS = -Wall -std=c11
CFLAGS += -I. # add the current directory to the include path
$(PROG1): manager.o
$(CC) $(CFLAGS) $^ -o $@
$(PROG2): worker.o
$(CC) $(CFLAGS) $^ -o $@
.Phone: run
run: $(PROG1) $(PROG2) # build and run the program
MY_MPIRUN_OPTIONS="-usize 8" mpirun -np 4 ./$(PROG1)
$(OBJECTS): %.o: %.c # compile the source files into object files
$(CC) $(CFLAGS) -c $<
.PHONY: clean
clean: # remove the object files and the binary
rm -f $(OBJECTS) $(PROG1) $(PROG2)
/****************************************************************
****************************************************************
****
**** This program file is part of the book and course
**** "Parallel Computing"
**** by Victor Eijkhout, copyright 2013-2020
****
**** spawn_manager.c : worker code for spawn example
****
****************************************************************
****************************************************************
*/
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
#define ASSERT(p) \
if (!(p)) { \
printf("Assertion failed for proc %d at line %d\n", procno, __LINE__); \
return -1; \
}
#define ASSERTm(p, m) \
if (!(p)) { \
printf("Message<<%s>> for proc %d at line %d\n", m, procno, __LINE__); \
return -1; \
}
MPI_Comm comm;
int procno = -1, nprocs;
MPI_Init(&argc, &argv);
comm = MPI_COMM_WORLD;
MPI_Comm_rank(comm, &procno);
MPI_Comm_size(comm, &nprocs);
/*
* To investigate process placement, get host name
*/
{
int namelen = MPI_MAX_PROCESSOR_NAME;
char procname[namelen];
MPI_Get_processor_name(procname, &namelen);
printf("[%d] manager process runs on <<%s>>\n", procno, procname);
}
int world_size, manager_rank, universe_size, *universe_sizep, flag;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
MPI_Comm_rank(MPI_COMM_WORLD, &manager_rank);
MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_UNIVERSE_SIZE, (void *)&universe_sizep,
&flag);
// codesnippet uverse
if (!flag) {
if (manager_rank == 0) {
printf("This MPI does not support UNIVERSE_SIZE.\nHow many processes "
"total?");
scanf("%d", &universe_size);
}
MPI_Bcast(&universe_size, 1, MPI_INTEGER, 0, MPI_COMM_WORLD);
// codesnippet end
} else {
universe_size = *universe_sizep;
if (manager_rank == 0)
printf("Universe size deduced as %d\n", universe_size);
}
ASSERTm(universe_size > world_size, "No room to start workers");
int nworkers = universe_size - world_size;
/*
* Now spawn the workers. Note that there is a run-time determination
* of what type of worker to spawn, and presumably this calculation must
* be done at run time and cannot be calculated before starting
* the program. If everything is known when the application is
* first started, it is generally better to start them all at once
* in a single MPI_COMM_WORLD.
*/
if (manager_rank == 0)
printf("Now spawning %d workers\n", nworkers);
const char *worker_program = "worker";
int errorcodes[nworkers];
MPI_Comm inter_to_workers; /* intercommunicator */
MPI_Comm_spawn(worker_program, MPI_ARGV_NULL, nworkers, MPI_INFO_NULL, 0,
MPI_COMM_WORLD, &inter_to_workers, errorcodes);
for (int ie = 0; ie < nworkers; ie++)
if (errorcodes[ie] != 0)
printf("Error %d in spawning worker %d\n", errorcodes[ie], ie);
/*
* Parallel code here. The communicator "inter_to_workers" can be used
* to communicate with the spawned processes, which have ranks 0,..
* MPI_UNIVERSE_SIZE-1 in the remote group of the intercommunicator
* "inter_to_workers".
*/
MPI_Finalize();
return 0;
}
/****************************************************************
****************************************************************
****
**** This program file is part of the book and course
**** "Parallel Computing"
**** by Victor Eijkhout, copyright 2013-6
****
**** spawn_worker.c : worker code for spawn example
****
****************************************************************
****************************************************************
*/
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
#define ASSERT(p) \
if (!(p)) { \
printf("Assertion failed for proc %d at line %d\n", procno, __LINE__); \
return -1; \
}
#define ASSERTm(p, m) \
if (!(p)) { \
printf("Message<<%s>> for proc %d at line %d\n", m, procno, __LINE__); \
return -1; \
}
MPI_Comm comm;
int procno = -1, nprocs;
MPI_Init(&argc, &argv);
comm = MPI_COMM_WORLD;
MPI_Comm_rank(comm, &procno);
MPI_Comm_size(comm, &nprocs);
MPI_Comm_set_errhandler(comm, MPI_ERRORS_RETURN);
int nworkers, workerno;
MPI_Comm parent;
// codesnippet spawnworker
MPI_Comm_size(MPI_COMM_WORLD, &nworkers);
MPI_Comm_rank(MPI_COMM_WORLD, &workerno);
MPI_Comm_get_parent(&parent);
// codesnippet end
ASSERTm(parent != MPI_COMM_NULL, "No parent!");
/*
* To investigate process placement, get host name
*/
{
int namelen = MPI_MAX_PROCESSOR_NAME;
char procname[namelen];
MPI_Get_processor_name(procname, &namelen);
printf("[%d] worker process runs on <<%s>>\n", workerno, procname);
}
/*
* Parallel code here.
* The manager is represented as the process with rank 0 in (the remote
* group of) MPI_COMM_PARENT. If the workers need to communicate among
* themselves, they can use MPI_COMM_WORLD.
*/
char hostname[256];
int namelen = 256;
MPI_Get_processor_name(hostname, &namelen);
printf("worker %d running on %s\n", workerno, hostname);
MPI_Finalize();
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment