Coconut
Coconut

Reputation: 184

MPI program with compiling options to be serial and parallel

I've wrote an MPI program and could be paralleled in C++. I would like to make it optional to be compiled for parallel or serial. Take the following hello world program, what's the common practice to achieve that? I saw some software compiled with option --serial/--parallel, but not sure how exactly it was done.

MPI version:

#include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {

    MPI_Init(&argc, &argv);

    int numprocs;
    int procid;
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &procid);

    printf("Hello world from process %d \n", procid);

    MPI_Finalize();
}

Serial Version:

#include <stdio.h>

int main(int argc, char** argv) {
    num = stoi(argv[1]);
    for (int i = 0; i < num; i++){
        printf("Hello world from process %d \n", num);
    }
}

Upvotes: 0

Views: 853

Answers (1)

jacob
jacob

Reputation: 1630

There are two levels in your question:

  • First, you may want to compile the same source code with and without MPI, producing two different programs---one parallel, one serial.
  • Or, you may want to compile one program (with MPI), but use command line option to specify whether the program is to be executed in serial or in parallel mode.

A code like the one below combines both.

If the first command-line argument is "-parallel", the program will start with the MPI initialization routine and terminate with the MPI finalization routine.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char *argv[])
{
    int iproc = 0;
    int nproc = 1;
    int par   = (strcmp(argv[1], "-parallel") == 0);
    int nwork = atoi(argv[2]);

    if (par) parallel_init(&argc, &argv, &iproc, &nproc);

    for (int i = 0; i < nwork; i++)
    {
        if (i % nproc == iproc)
        {
            printf("Running task %d by rank %d\n", i, iproc);
            /* ... etc ... */
        }
    }

    if (par) parallel_final();

    return 0;
}

Also, you can compile this source without the need for MPI at all by passing the -DNOMPI flag to the compiler.

#ifndef NOMPI
#include <mpi.h>
#endif

void parallel_init (int *pargc, char **pargv[], int *piproc, int *pnproc)
{
#ifdef NOMPI
    *piproc = 0;
    *pnproc = 1;
#else
    MPI_Init(pargc, pargv);
    MPI_Comm_size(MPI_COMM_WORLD, pnproc);
    MPI_Comm_rank(MPI_COMM_WORLD, piproc);
#endif
}

void parallel_final ()
{
#ifndef NOMPI
    MPI_Finalize();
#endif
}

E.g.,

> mpicc main.c 
> ./a.out -serial 4
Running task 0 by rank 0
Running task 1 by rank 0
Running task 2 by rank 0
Running task 3 by rank 0
> mpiexec -n 2 ./a.out -parallel 4
Running task 0 by rank 0
Running task 2 by rank 0
Running task 1 by rank 1
Running task 3 by rank 1

Upvotes: 1

Related Questions