Subversion Repositories programming

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*******************************************************************************
 * prob3.c - implement a parallel (pipelined approach) system for the
 *           Sieve of Eratosthenes problem.
 *
 * Copyright (c) 2006, Ira W. Snyder (devel@irasnyder.com)
 ******************************************************************************/

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

#define TAG_DATA   0x1010
#define TERMINATOR 0xffff
#define BAD_NUM    -1

#define FALSE 0
#define TRUE  1

int should_pass (int num, int mynumber)
{
    if (num % mynumber == 0)
        return FALSE; // evenly divisible, DO NOT PASS

    return TRUE; // not evenly divisible, GO AHEAD
}

void print_num (int myrank, int mynumber)
{
    if (mynumber == BAD_NUM)
        return;

    if (myrank < 10)
        printf ("Proc 0%d's Prime: %d\n", myrank, mynumber);
    else
        printf ("Proc %d's Prime: %d\n", myrank, mynumber);
}

void send_term (int to_proc)
{
    int temp = TERMINATOR;
    MPI_Send (&temp, 1, MPI_INT, to_proc, TAG_DATA, MPI_COMM_WORLD);
}

int main (int argc, char *argv[])
{
    int myrank, numprocs;
    int mynumber = BAD_NUM;
    int temp_recv;

    MPI_Status status;

    MPI_Init (&argc, &argv);
    MPI_Comm_rank (MPI_COMM_WORLD, &myrank);
    MPI_Comm_size (MPI_COMM_WORLD, &numprocs);

    if (myrank == 0)
    {
        int i;
        mynumber = 2;
        
        for (i=3; i<=100; i++)
            if (should_pass (i, mynumber))
                MPI_Send (&i, 1, MPI_INT, myrank+1, TAG_DATA, MPI_COMM_WORLD);

        send_term (myrank+1);
    }
    else if (myrank < (numprocs - 1))
    {
        /* Save the first number we recieve */
        MPI_Recv (&mynumber, 1, MPI_INT, myrank-1, TAG_DATA, MPI_COMM_WORLD, &status);

        /* Check if we need to exit early */
        if (mynumber == TERMINATOR)
        {
            send_term (myrank+1);
            goto END_NOW;
        }

        /* Check all subsequent numbers */
        while (TRUE)
        {
            MPI_Recv (&temp_recv, 1, MPI_INT, myrank-1, TAG_DATA, MPI_COMM_WORLD, &status);

            if (temp_recv == TERMINATOR)
            {
                send_term (myrank+1);
                break;
            }
            else
            {
                if (should_pass (temp_recv, mynumber))
                    MPI_Send (&temp_recv, 1, MPI_INT, myrank+1, TAG_DATA, MPI_COMM_WORLD);
            }
        }
    }
    else 
    {
        /* Save the first number we recieve */
        MPI_Recv (&mynumber, 1, MPI_INT, myrank-1, TAG_DATA, MPI_COMM_WORLD, &status);

        if (mynumber == TERMINATOR)
            goto END_NOW;

        while (TRUE)
        {
            MPI_Recv (&temp_recv, 1, MPI_INT, myrank-1, TAG_DATA, MPI_COMM_WORLD, &status);

            if (temp_recv == TERMINATOR)
                break;
            else
                if (should_pass (temp_recv, mynumber))
                {
                    printf ("ERROR: not enough processes.\n");
                    printf ("Prime: %d\n", temp_recv);
                }
        }
    }

END_NOW:
    print_num (myrank, mynumber);

    MPI_Finalize ();

    return 0;
}