Subversion Repositories programming

Rev

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

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

const int ROOT_NODE = 0;
int numprocs;
int myid;

/**
 * NOTE: Accessing "matrices" in this program is a little strange.
 * I decided to implement matrices using an array. To get to a[row][col],
 * you would use a[row*a_size+col]. Pretty simple actually.
 */

int* allocate (int rows, int cols)
{
    int *temp = NULL;

    if ((temp = (int*) malloc (rows * cols * sizeof(int))) == NULL)
        printf ("Could not allocate memory for array of size: %d x %d\n", rows, cols);

    return temp;
}

void print_matrix (int *b, int n, const char *s)
{
    int i,j;

    if (n<=10) // n<=10
    {
        printf ("%s\n", s);

        for (i=0; i<n; i++)
        {
            for (j=0; j<n; j++)
                printf ("%d\t", b[i*n+j]);

            printf ("\n");
        }
        printf ("\n");
    }
    else if (n<=100) // 10<n<=100
    {
        printf ("%s\n", s);

        // First 2 rows
        for (i=0; i<2; i++)
        {
            for (j=0; j<n; j++)
                printf ("%d\t", b[i*n+j]);

            printf ("\n");
        }
        printf ("\n");

        // First 2 cols
        for (i=0; i<n; i++)
        {
            for (j=0; j<2; j++)
                printf ("%d\t", b[i*n+j]);

            printf ("\n");
        }
    }
}

void matrix_mult (int *b, int *c, int n)
{
    int i,j,k,ii,temp;

    /* Multiply our slice of the matrix, store it in c */
    for (ii=0; ii<n/numprocs; ii++)
    {
        i = ii + myid * n/numprocs; // i is the offset into b

        for (j=0; j<n; j++)
        {
            // MATRIX_MULT
            // c[i*n+j]=0;

            // SHORTEST PATH
            c[ii*n+j] = INT_MAX;

            for (k=0; k<n; k++)
            {
                // MATRIX MULT
                // c[i*n+j] += a[i*n+k] * b[k*n+j];

                // SHORTEST PATH
                if (b[i*n+k] == INT_MAX || b[k*n+j] == INT_MAX)
                    temp = INT_MAX;
                else
                    temp = b[i*n+k] + b[k*n+j];

                if (temp < c[ii*n+j])
                    c[ii*n+j] = temp;
            }
        }
    }
}

int main (int argc, char *argv[])
{
    const int n = 4;
    int *b, *c;
    int i, j, k, temp, t;
    MPI_Status status;

    /* Get all of the necessary info for each process */
    MPI_Init (&argc, &argv);
    MPI_Comm_rank (MPI_COMM_WORLD, &myid);
    MPI_Comm_size (MPI_COMM_WORLD, &numprocs);

    /* Do a quick sanity check for the correct number of processors */
    if (n % numprocs != 0)
    {
        if (myid == 0)
        {
            printf ("%d mod %d must be zero!\n", n, numprocs);
            printf ("You should probably change the -np parameter\n");
        }

        MPI_Finalize ();
        return 1;
    }

    /* Allocate all of b for each process, since we'll need it */
    b = allocate (n, n);

    if (myid == ROOT_NODE)
    {
        /* Allocate the full c, since we need to initialize it */
        c = allocate (n, n);

        /* Initialize values */
        for (i=0; i<n; i++)
            for (j=0; j<n; j++)
                b[i*n+j] = INT_MAX;

        b[0] = 0;
        b[1] = 2;
        b[2] = INT_MAX;
        b[3] = 10;

        b[4] = 2;
        b[5] = 0;
        b[6] = 2;
        b[7] = INT_MAX;

        b[8]  = INT_MAX;
        b[9]  = 2;
        b[10] = 0;
        b[11] = 3;

        b[12] = 10;
        b[13] = INT_MAX;
        b[14] = 3;
        b[15] = 0;

        if (n<=100)
            print_matrix (b, n, "Input Matrix:");
        else
        {
            printf ("Beginning calculation for all shortest paths\n");
            printf ("for a graph with %d nodes\n", n);
        }

    }
    else
    {
        /* Allocate our slice of c, since that's all we need */
        c = allocate (n/numprocs, n);
    }

    /* Send all of b to each process, since they need all of it */
    MPI_Bcast (b, n*n, MPI_INT, ROOT_NODE, MPI_COMM_WORLD);

    /* Run our piece of the calculation.
     * Synchronize data with all other processes at the end of each step. */
    for (t=0; t<ceil(log(n-1)); t++)
    {
        matrix_mult (b, c, n);
        MPI_Allgather (c, n*n/numprocs, MPI_INT, b, n*n/numprocs, MPI_INT, MPI_COMM_WORLD);
    }

    /* Print out the result matrix. */
    if (myid == ROOT_NODE)
    {
        if (n<=100)
            print_matrix (b, n, "Result Matrix:");
        else
        {
            printf ("Finished calculation for all shortest paths\n");
            printf ("for a graph with %d nodes\n", n);
        }
    }

    /* Free all of the memory we allocated earlier */
    free (b);
    free (c);

    MPI_Finalize ();
    return 0;
}