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