Subversion Repositories programming

Rev

Rev 326 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
327 ira 1
/* proj3_random.c - implements the APSP algorithm for a matrix of size nxn
2
 *                  as provided in the project description, randomly generating
3
 *                  the weight matrix.
4
 *
5
 * Copyright (c) 2006, Ira W. Snyder (devel@irasnyder.com)
6
 */
7
 
8
 
322 ira 9
#include <stdio.h>
327 ira 10
#include <stdlib.h>
322 ira 11
#include <limits.h>
12
#include <mpi.h>
327 ira 13
#include <unistd.h>
322 ira 14
 
15
const int ROOT_NODE = 0;
325 ira 16
int numprocs;
17
int myid;
322 ira 18
 
327 ira 19
#ifdef SOLARIS
20
 
21
    /* NOTE: Solaris is broken, and RAND_MAX is NOT the maximum size
22
     * number that random() outputs. Here is the correct value. */
23
    #define RAND_MAX LONG_MAX
24
 
25
#endif
26
 
322 ira 27
/**
28
 * NOTE: Accessing "matrices" in this program is a little strange.
29
 * I decided to implement matrices using an array. To get to a[row][col],
30
 * you would use a[row*a_size+col]. Pretty simple actually.
31
 */
32
 
33
int* allocate (int rows, int cols)
34
{
35
    int *temp = NULL;
36
 
37
    if ((temp = (int*) malloc (rows * cols * sizeof(int))) == NULL)
38
        printf ("Could not allocate memory for array of size: %d x %d\n", rows, cols);
39
 
40
    return temp;
41
}
42
 
325 ira 43
void print_matrix (int *b, int n, const char *s)
44
{
45
    int i,j;
46
 
47
    if (n<=10) // n<=10
48
    {
49
        printf ("%s\n", s);
50
 
51
        for (i=0; i<n; i++)
52
        {
53
            for (j=0; j<n; j++)
54
                printf ("%d\t", b[i*n+j]);
55
 
56
            printf ("\n");
57
        }
58
        printf ("\n");
59
    }
60
    else if (n<=100) // 10<n<=100
61
    {
62
        printf ("%s\n", s);
63
 
64
        // First 2 rows
65
        for (i=0; i<2; i++)
66
        {
67
            for (j=0; j<n; j++)
68
                printf ("%d\t", b[i*n+j]);
69
 
70
            printf ("\n");
71
        }
72
        printf ("\n");
73
 
74
        // First 2 cols
75
        for (i=0; i<n; i++)
76
        {
77
            for (j=0; j<2; j++)
78
                printf ("%d\t", b[i*n+j]);
79
 
80
            printf ("\n");
81
        }
82
    }
83
}
84
 
85
void matrix_mult (int *b, int *c, int n)
86
{
87
    int i,j,k,ii,temp;
88
 
89
    /* Multiply our slice of the matrix, store it in c */
90
    for (ii=0; ii<n/numprocs; ii++)
91
    {
92
        i = ii + myid * n/numprocs; // i is the offset into b
93
 
94
        for (j=0; j<n; j++)
95
        {
96
            // MATRIX_MULT
97
            // c[i*n+j]=0;
98
 
99
            // SHORTEST PATH
100
            c[ii*n+j] = INT_MAX;
101
 
102
            for (k=0; k<n; k++)
103
            {
104
                // MATRIX MULT
105
                // c[i*n+j] += a[i*n+k] * b[k*n+j];
106
 
107
                // SHORTEST PATH
108
                if (b[i*n+k] == INT_MAX || b[k*n+j] == INT_MAX)
109
                    temp = INT_MAX;
110
                else
111
                    temp = b[i*n+k] + b[k*n+j];
112
 
113
                if (temp < c[ii*n+j])
114
                    c[ii*n+j] = temp;
115
            }
116
        }
117
    }
118
}
119
 
322 ira 120
int main (int argc, char *argv[])
121
{
327 ira 122
    const int n = 10;
325 ira 123
    int *b, *c;
124
    int i, j, k, temp, t;
125
    MPI_Status status;
322 ira 126
 
127
    /* Get all of the necessary info for each process */
128
    MPI_Init (&argc, &argv);
129
    MPI_Comm_rank (MPI_COMM_WORLD, &myid);
130
    MPI_Comm_size (MPI_COMM_WORLD, &numprocs);
131
 
326 ira 132
    /* Do a quick sanity check for the correct number of processors */
133
    if (n % numprocs != 0)
134
    {
135
        if (myid == 0)
136
        {
137
            printf ("%d mod %d must be zero!\n", n, numprocs);
138
            printf ("You should probably change the -np parameter\n");
139
        }
140
 
141
        MPI_Finalize ();
142
        return 1;
143
    }
144
 
322 ira 145
    /* Allocate all of b for each process, since we'll need it */
146
    b = allocate (n, n);
147
 
148
    if (myid == ROOT_NODE)
149
    {
325 ira 150
        /* Allocate the full c, since we need to initialize it */
322 ira 151
        c = allocate (n, n);
152
 
327 ira 153
        /* Seed the rng */
154
        srandom (time(NULL));
155
 
156
        /* Initialize values to random number in [1,100] */
322 ira 157
        for (i=0; i<n; i++)
158
            for (j=0; j<n; j++)
327 ira 159
                b[i*n+j] = (int) (1.0 + (100.0 * (random() / (RAND_MAX + 1.0))));
324 ira 160
 
327 ira 161
        /* Force b[i][i] = 0 */
162
        for (i=0; i<n; i++)
163
            b[i*n+i] = 0; 
323 ira 164
 
325 ira 165
        if (n<=100)
166
            print_matrix (b, n, "Input Matrix:");
167
        else
168
        {
169
            printf ("Beginning calculation for all shortest paths\n");
170
            printf ("for a graph with %d nodes\n", n);
171
        }
172
 
322 ira 173
    }
174
    else
175
    {
325 ira 176
        /* Allocate our slice of c, since that's all we need */
322 ira 177
        c = allocate (n/numprocs, n);
178
    }
179
 
325 ira 180
    /* Send all of b to each process, since they need all of it */
322 ira 181
    MPI_Bcast (b, n*n, MPI_INT, ROOT_NODE, MPI_COMM_WORLD);
182
 
325 ira 183
    /* Run our piece of the calculation.
184
     * Synchronize data with all other processes at the end of each step. */
185
    for (t=0; t<ceil(log(n-1)); t++)
322 ira 186
    {
325 ira 187
        matrix_mult (b, c, n);
188
        MPI_Allgather (c, n*n/numprocs, MPI_INT, b, n*n/numprocs, MPI_INT, MPI_COMM_WORLD);
322 ira 189
    }
190
 
325 ira 191
    /* Print out the result matrix. */
322 ira 192
    if (myid == ROOT_NODE)
193
    {
325 ira 194
        if (n<=100)
195
            print_matrix (b, n, "Result Matrix:");
196
        else
323 ira 197
        {
325 ira 198
            printf ("Finished calculation for all shortest paths\n");
199
            printf ("for a graph with %d nodes\n", n);
323 ira 200
        }
322 ira 201
    }
202
 
203
    /* Free all of the memory we allocated earlier */
204
    free (b);
205
    free (c);
206
 
207
    MPI_Finalize ();
208
    return 0;
209
}
210