Subversion Repositories programming

Rev

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

Rev Author Line No. Line
294 ira 1
/*******************************************************************************
303 ira 2
 * proj1-parallel.c - implement a simple program that will find the minimum
3
 *                    and maximum numbers out of a randomly generated list of
4
 *                    integers, using MPI to parallelize the operation.
294 ira 5
 *
6
 * Copyright (c) 2006, Ira W. Snyder (devel@irasnyder.com)
7
 * All rights reserved.
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy
10
 * of this software and associated documentation files (the "Software"), to
11
 * deal in the Software without restriction, including without limitation the
12
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13
 * sell copies of the Software, and to permit persons to whom the Software is
14
 * furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in
17
 * all copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25
 * IN THE SOFTWARE.
26
 ******************************************************************************/
27
 
303 ira 28
#include <limits.h>
294 ira 29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <unistd.h>
32
 
303 ira 33
#include <mpi.h>
34
 
35
#define ROOT_NODE 0
36
#define TAG_MAX  0x1010
37
#define TAG_MIN  0x0101
38
#define TAG_SIZE 0x0808
39
#define TAG_DATA 0x0c0c
40
 
41
void find_max_and_min (const int *numbers, const int size, int *max, int *min)
42
{
43
    int i;
44
    *max = INT_MIN;
45
    *min = INT_MAX;
46
 
47
    for (i=0; i<size; i++)
48
    {
49
        if (numbers[i] > *max)
50
            *max = numbers[i];
51
 
52
        if (numbers[i] < *min)
53
            *min = numbers[i];
54
    }
55
}
56
 
305 ira 57
void print_local_max_and_min (const int proc_id, const int max, const int min)
58
{
59
    printf ("Local max for process %d: %d\n", proc_id, max);
60
    printf ("Local min for process %d: %d\n", proc_id, min);
61
}
62
 
294 ira 63
int main (int argc, char *argv[])
64
{
304 ira 65
    int numprocs, myid, i;
66
    int n = -1;
67
    int c = -1;
294 ira 68
 
303 ira 69
    int size;
294 ira 70
    int *numbers;
71
 
303 ira 72
    int max = INT_MIN;
73
    int min = INT_MAX;
294 ira 74
 
305 ira 75
    int temp_max, temp_min;
303 ira 76
 
77
    MPI_Status status;
78
 
79
    MPI_Init (&argc, &argv);
80
    MPI_Comm_size (MPI_COMM_WORLD, &numprocs);
81
    MPI_Comm_rank (MPI_COMM_WORLD, &myid);
82
 
83
    if (myid == ROOT_NODE)
294 ira 84
    {
304 ira 85
        /* Parse the command line options */
86
        opterr = 0;
87
 
88
        while ((c = getopt (argc, argv, "n:")) != -1)
89
        {
90
            switch (c)
91
            {
92
                /* Try to get -n option */
93
                case 'n':
94
                    n = atoi (optarg);
95
                    break;
96
 
97
                /* Catch bad options */
98
                case '?':
99
                    if (isprint (optopt))
100
                        fprintf (stderr, "Unknown option '-%c'.\n", optopt);
101
                    else
102
                        fprintf (stderr, "Unknown option character '\\x%x'.\n", optopt);
103
 
104
                    return 1;
105
                    break;
106
                default:
107
                    abort ();
108
            }
109
        }
110
 
111
        /* Check if the n value is valid */
112
        if (n<=0)
113
        {
114
            fprintf (stderr, "Bad value for n, must be greater than 0\n");
115
            fprintf (stderr, "Please specify the '-n NUMBER' option\n");
116
            return 1;
117
        }
118
 
305 ira 119
        /* Make sure that we have the ability to calculate the answer */
120
        if (n % numprocs != 0)
121
        {
122
            fprintf (stderr, "n must be evenly divisble by numprocs\n");
123
            fprintf (stderr, "Please adjust -n and -np adequately\n");
124
            return 2;
125
        }
126
 
304 ira 127
        /* Allocate memory for the random number array */
303 ira 128
        if ((numbers = (int*) malloc (n * sizeof(int))) == NULL)
294 ira 129
        {
303 ira 130
            puts ("Out of memory");
131
            return 1;
132
        }
294 ira 133
 
305 ira 134
        /* Seed the random number generator */
135
        srand (time(NULL));
136
 
304 ira 137
        /* Generate random numbers, staying in the range [0,10n) */
303 ira 138
        for (i=0; i<n; i++)
304 ira 139
            numbers[i] = (int) ((n*10.0) * rand() / (RAND_MAX + 1.0));
294 ira 140
 
303 ira 141
        /* Calculate slice size */
142
        size = n/numprocs;
294 ira 143
 
303 ira 144
        /* Send out n to everyone */
145
        for (i=1; i<numprocs; i++)
146
            MPI_Send (&size, 1, MPI_INT, i, TAG_SIZE, MPI_COMM_WORLD);
147
 
148
        /* Send out data to everyone */
149
        for (i=1; i<numprocs; i++)
150
            MPI_Send (numbers+(size*i), size, MPI_INT, i, TAG_DATA, MPI_COMM_WORLD);
151
 
305 ira 152
        /* Print some information */
153
        printf ("Size of the List: %d\n", n);
154
        printf ("No. of processes: %d\n\n", numprocs);
155
 
303 ira 156
        /* Calculate my part of the data */
157
        find_max_and_min (numbers, size, &max, &min);
158
 
305 ira 159
        print_local_max_and_min (myid, max, min);
160
 
303 ira 161
        /* Recieve data back */
162
        for (i=1; i<numprocs; i++)
163
        {
164
            /* Find actual max */
305 ira 165
            MPI_Recv (&temp_max, 1, MPI_INT, i, TAG_MAX, MPI_COMM_WORLD, &status);
166
 
167
            if (temp_max > max)
168
                max = temp_max;
303 ira 169
 
170
            /* Find actual min */
305 ira 171
            MPI_Recv (&temp_min, 1, MPI_INT, i, TAG_MIN, MPI_COMM_WORLD, &status);
303 ira 172
 
305 ira 173
            if (temp_min < min)
174
                min = temp_min;
175
 
176
            print_local_max_and_min (i, temp_max, temp_min);
294 ira 177
        }
303 ira 178
 
305 ira 179
        printf ("\nOverall max: %d\n", max);
180
        printf ("Overall min: %d\n", min);
294 ira 181
    }
304 ira 182
    else // not ROOT_NODE
303 ira 183
    {
184
        /* Recieve size of the data */
185
        MPI_Recv (&size, 1, MPI_INT, ROOT_NODE, TAG_SIZE, MPI_COMM_WORLD, &status);
294 ira 186
 
303 ira 187
        /* Allocate memory to store the data */
188
        if ((numbers = (int*) malloc (size * sizeof(int))) == NULL)
189
        {
190
            puts ("Out of memory");
191
            return 1;
192
        }
294 ira 193
 
303 ira 194
        /* Recieve the data */
195
        MPI_Recv (numbers, size, MPI_INT, ROOT_NODE, TAG_DATA, MPI_COMM_WORLD, &status);
294 ira 196
 
303 ira 197
        /* Calculate the max and min of my part of the data */
198
        find_max_and_min (numbers, size, &max, &min);
294 ira 199
 
303 ira 200
        /* Send the max and min back to the root node */
201
        MPI_Send (&max, 1, MPI_INT, ROOT_NODE, TAG_MAX, MPI_COMM_WORLD);
202
        MPI_Send (&min, 1, MPI_INT, ROOT_NODE, TAG_MIN, MPI_COMM_WORLD);
294 ira 203
    }
204
 
305 ira 205
    free (numbers);
303 ira 206
    MPI_Finalize ();
294 ira 207
 
208
    return 0;
209
}
210