Subversion Repositories programming

Rev

Rev 303 | Go to most recent revision | 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
 
294 ira 57
int main (int argc, char *argv[])
58
{
304 ira 59
    int numprocs, myid, i;
60
    int n = -1;
61
    int c = -1;
294 ira 62
 
303 ira 63
    int size;
294 ira 64
    int *numbers;
65
 
303 ira 66
    int max = INT_MIN;
67
    int min = INT_MAX;
294 ira 68
 
303 ira 69
    int temp;
70
 
71
    MPI_Status status;
72
 
73
    MPI_Init (&argc, &argv);
74
    MPI_Comm_size (MPI_COMM_WORLD, &numprocs);
75
    MPI_Comm_rank (MPI_COMM_WORLD, &myid);
76
 
77
    if (myid == ROOT_NODE)
294 ira 78
    {
304 ira 79
        /* Parse the command line options */
80
        opterr = 0;
81
 
82
        while ((c = getopt (argc, argv, "n:")) != -1)
83
        {
84
            switch (c)
85
            {
86
                /* Try to get -n option */
87
                case 'n':
88
                    n = atoi (optarg);
89
                    break;
90
 
91
                /* Catch bad options */
92
                case '?':
93
                    if (isprint (optopt))
94
                        fprintf (stderr, "Unknown option '-%c'.\n", optopt);
95
                    else
96
                        fprintf (stderr, "Unknown option character '\\x%x'.\n", optopt);
97
 
98
                    return 1;
99
                    break;
100
                default:
101
                    abort ();
102
            }
103
        }
104
 
105
        /* Seed the random number generator */
106
        srand (time(NULL));
107
 
108
        /* Check if the n value is valid */
109
        if (n<=0)
110
        {
111
            fprintf (stderr, "Bad value for n, must be greater than 0\n");
112
            fprintf (stderr, "Please specify the '-n NUMBER' option\n");
113
            return 1;
114
        }
115
 
116
        /* Allocate memory for the random number array */
303 ira 117
        if ((numbers = (int*) malloc (n * sizeof(int))) == NULL)
294 ira 118
        {
303 ira 119
            puts ("Out of memory");
120
            return 1;
121
        }
294 ira 122
 
304 ira 123
        /* Generate random numbers, staying in the range [0,10n) */
303 ira 124
        for (i=0; i<n; i++)
304 ira 125
            numbers[i] = (int) ((n*10.0) * rand() / (RAND_MAX + 1.0));
294 ira 126
 
303 ira 127
        /* Calculate slice size */
128
        size = n/numprocs;
294 ira 129
 
303 ira 130
        /* Send out n to everyone */
131
        for (i=1; i<numprocs; i++)
132
            MPI_Send (&size, 1, MPI_INT, i, TAG_SIZE, MPI_COMM_WORLD);
133
 
134
        /* Send out data to everyone */
135
        for (i=1; i<numprocs; i++)
136
            MPI_Send (numbers+(size*i), size, MPI_INT, i, TAG_DATA, MPI_COMM_WORLD);
137
 
138
        /* Calculate my part of the data */
139
        find_max_and_min (numbers, size, &max, &min);
140
 
141
        /* Recieve data back */
142
        for (i=1; i<numprocs; i++)
143
        {
144
            /* Find actual max */
145
            MPI_Recv (&temp, 1, MPI_INT, i, TAG_MAX, MPI_COMM_WORLD, &status);
146
 
147
            if (temp > max)
148
                max = temp;
149
 
150
            /* Find actual min */
151
            MPI_Recv (&temp, 1, MPI_INT, i, TAG_MIN, MPI_COMM_WORLD, &status);
152
 
153
            if (temp < min)
154
                min = temp;
294 ira 155
        }
303 ira 156
 
157
        printf ("final max: %d\n", max);
158
        printf ("final min: %d\n", min);
294 ira 159
    }
304 ira 160
    else // not ROOT_NODE
303 ira 161
    {
162
        /* Recieve size of the data */
163
        MPI_Recv (&size, 1, MPI_INT, ROOT_NODE, TAG_SIZE, MPI_COMM_WORLD, &status);
294 ira 164
 
303 ira 165
        /* Allocate memory to store the data */
166
        if ((numbers = (int*) malloc (size * sizeof(int))) == NULL)
167
        {
168
            puts ("Out of memory");
169
            return 1;
170
        }
294 ira 171
 
303 ira 172
        /* Recieve the data */
173
        MPI_Recv (numbers, size, MPI_INT, ROOT_NODE, TAG_DATA, MPI_COMM_WORLD, &status);
294 ira 174
 
303 ira 175
        /* Calculate the max and min of my part of the data */
176
        find_max_and_min (numbers, size, &max, &min);
294 ira 177
 
303 ira 178
        /* Send the max and min back to the root node */
179
        MPI_Send (&max, 1, MPI_INT, ROOT_NODE, TAG_MAX, MPI_COMM_WORLD);
180
        MPI_Send (&min, 1, MPI_INT, ROOT_NODE, TAG_MIN, MPI_COMM_WORLD);
294 ira 181
 
303 ira 182
        free (numbers);
294 ira 183
    }
184
 
303 ira 185
    MPI_Finalize ();
294 ira 186
 
187
    return 0;
188
}
189