Distribute work and data on MPI processes

Viewed 82

I write a serial program to calculate pi from tan(pi/4)=1 => pi = 4*(1/1+x^2) using the integral representation of arctan. Therefore, we can evaluate pi as the integral of f(x) from 0 to 1 with f(x)=4*(1/1+x*x). The integral is approximated by a sum of N intervals.

The number of intervals N should be read from stdin, and N and pi should be written to stdout. Parallelize this program with MPI, so that only the MPI process with rank=0 reads N from stdin and then distributes this information to all other processes. In the end only the MPI process with rank=0 should write size, N, and pi to stdout.

I didn't understand the following part, like how to assign the computation in the processes like this?

Pay attendion how you distribute the work & data, please program both options: n=0,1,2,3,4,5,6,7,... N-1 -> the intervals
1.a: p=0,1,2,3,0,1,2,3, ... -> process that computes this interval, here with size 4
1.b: p=0,0,0 ..., 1,1,1 ..., 2,2,2 ..., 3,3,3 ... -> process that computes this interval Which one is the better option and why?

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

double f(double a)
{
    return (4.0 / (1.0 + a * a));
}

int main(int argc, char* argv[])
{
    int done = 0, n, myid, numprocs, i;
    double PI25DT = 3.141592653589793238462643;
    double mypi, pi, h, sum, x;
    double startwtime = 0.0, endwtime;
    int namelen;
    char processor_name[MPI_MAX_PROCESSOR_NAME];
    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
    MPI_Get_processor_name(processor_name, &namelen);
    fprintf(stderr, "Process %d on %s\n",
        myid, processor_name);

    n = 0;
    while (!done)
    {
        if (myid == 0)
        {

             printf("Enter the number of intervals: (0 quits) ");
             scanf("%d",&n);

            if (n == 0)
                n = 1024 * numprocs;
            else
                n = 0;

            startwtime = MPI_Wtime();
        }
        MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
        if (n == 0)
            done = 1;
        else
        {
            h = 1.0 / (double)n;
            sum = 0.0;
            for (i = myid + 1; i <= n; i += numprocs)
            {
                x = h * ((double)i - 0.5);
                sum += f(x);
            }
            mypi = h * sum;

            MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

            if (myid == 0)
            {
                printf("pi is approximately %.16f, Error is %.16f\n",
                    pi, fabs(pi - PI25DT));
                endwtime = MPI_Wtime();
                printf("wall clock time = %f\n",
                    endwtime - startwtime);
            }
        }
    }
    MPI_Finalize();
    return 0;
}

scanf issue

After creating the executable file, I run the program:

mpiexec -n 4 .\pi.exe

And the program was stuck after printing this:

Process 3 on DESKTOP-2E69SSG
Process 2 on DESKTOP-2E69SSG
Process 1 on DESKTOP-2E69SSG
Process 0 on DESKTOP-2E69SSG

I couldn't understand why it was stuck. I add #define _CRT_SECURE_NO_DEPRECATE because it shows warning for scanf

Warning C6031   Return value ignored: 'scanf'.

If I comment out the scanf part, then the program run as expected,

Process 3 on DESKTOP-2E69SSG
Process 2 on DESKTOP-2E69SSG
Process 1 on DESKTOP-2E69SSG
Process 0 on DESKTOP-2E69SSG
pi is approximately 3.1415926585568474, Error is 0.0000000049670543
wall clock time = 0.001012

second part

I actually don't understand the second part of that question. Like how I distribute the calculation on processes like the mentioned pattern? One way would be for the 1.a: p=0,1,2,3,0,1,2,3, ... -> process that computes this interval,

    for (int i = 0; i < size; i++)
    {
        if (i == rank) {
           // do stuff
        }
        MPI_Barrier(MPI_COMM_WORLD);
    }

How to resolve these issues?

Thanks in advance.

0 Answers
Related