File: trsg.c

package info (click to toggle)
pvm 3.4.6-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 8,284 kB
  • sloc: ansic: 72,074; makefile: 1,198; fortran: 631; sh: 285; csh: 74; asm: 37
file content (234 lines) | stat: -rw-r--r-- 7,256 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

static char rcsid[] =
	"$Id: trsg.c,v 1.6 2009/01/23 01:20:23 pvmsrc Exp $";

/*
 *         PVM version 3.4:  Parallel Virtual Machine System
 *               University of Tennessee, Knoxville TN.
 *           Oak Ridge National Laboratory, Oak Ridge TN.
 *                   Emory University, Atlanta GA.
 *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
 *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
 *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
 *                   (C) 1997 All Rights Reserved
 *
 *                              NOTICE
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted
 * provided that the above copyright notice appear in all copies and
 * that both the copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * Neither the Institutions (Emory University, Oak Ridge National
 * Laboratory, and University of Tennessee) nor the Authors make any
 * representations about the suitability of this software for any
 * purpose.  This software is provided ``as is'' without express or
 * implied warranty.
 *
 * PVM version 3 was funded in part by the U.S. Department of Energy,
 * the National Science Foundation and the State of Tennessee.
 */

/*
 * Example of group Reduce, Scatter, and Gather functions - J.M. Donato
 * 
 * This example calculates the sum of squares of the first N integers
 * in three different ways where 
 *
 *   N = (number of processors)*(number of elements per row)
 *
 * Note:  This is obviously not an efficient way to compute the 
 *        sum of squares, but it is a cutesy example and test case.
 */

#include <stdio.h>
#ifdef HASSTDLIB
#include <stdlib.h>
#endif
#include "pvm3.h"

#define MAXNDATA  20
#define MAXNPROCS 16
#define DFLTNDATA 5
#define DFLTNPROCS 4
#define TASK_NAME "trsg"

#ifdef WIN32
#undef min
#undef max
#endif

#define min(x,y) ( ((x)<(y))? (x) : (y) )
#define max(x,y) ( ((x)>(y))? (x) : (y) )

extern void PvmMin();
extern void PvmMax();
extern void PvmSum();
extern void PvmProduct();

void MaxWithLoc();

main()
{
  int myginst, i, j, gsize, count, nprocs, msgtag, datatype; 
  int info_product, info_user; 
  int  tids[MAXNPROCS], myrow[MAXNDATA], matrix[MAXNDATA*MAXNPROCS]; 
  float values[2];
  int midpoint, bigN, Sum1=0, Sum2=0, SumSquares, rootginst; 
  int PSum = 0, PartSums[MAXNPROCS], dupls[MAXNDATA];
  char *gname = "group_rsg";

  /* join the group */
  myginst = pvm_joingroup(gname);
  pvm_setopt(PvmAutoErr, 1);

  /* I am the first group member, get input, start up copies of myself */
  if ( myginst == 0 )       
  {
    if (pvm_parent() == PvmNoParent)
    {
      printf("\n *** Example use of PVM Reduce, Scatter, and Gather *** ");
      printf("\n Number of processors to use (1-%d)? : ", MAXNPROCS);
      scanf("%d", &nprocs);
      if (nprocs > MAXNPROCS) nprocs = MAXNPROCS;
      printf(" Number of elements per row to use (1-%d)? : ", MAXNDATA);
      scanf("%d", &count);
      if (count > MAXNDATA) count = MAXNDATA;
      printf(" INPUT values: nprocs = %d, count = %d \n", nprocs, count);
    }
    else
    {
      count = DFLTNDATA;
      nprocs = DFLTNPROCS;
    }

    tids[0] = pvm_mytid();

    if (nprocs > 1)
      pvm_spawn(TASK_NAME, (char**)0, 0, "", nprocs-1, &tids[1]);

    /* wait until they have all started, then send input values */
    while (gsize = pvm_gsize(gname) < nprocs) 
		pvmsleep(1);

	pvm_initsend(PvmDataDefault);
    pvm_pkint(&nprocs, 1, 1);
    pvm_pkint(&count,  1, 1);
    pvm_bcast(gname, msgtag=17);
  }
  else
  {
    /* receive the input values */
    pvm_recv(-1, msgtag=17);
    pvm_upkint(&nprocs, 1, 1);
    pvm_upkint(&count,  1, 1);
  }
  
  rootginst = 0;  /* determine the group root */

  /* init the matrix values on the root processor */
  if (myginst == rootginst) 
    for (j=0; j<nprocs; j++)
      for (i=0; i<count; i++)
        matrix[j*count + i] = j*count + i + 1;

  /* scatter rows of matrix to each processor */
  pvm_scatter(myrow, matrix, count, PVM_INT, msgtag=19, gname, rootginst);

  /* this should end up squaring each value on each processor */
  for (i=0; i<count; i++) dupls[i] = (myginst*count + i + 1);
  datatype = PVM_INT;
  PvmProduct(&datatype, myrow, dupls, &count, &info_product);
  if ((myginst == rootginst) && (info_product < 0))
      printf(" ERROR: %d on PvmProduct call \n", info_product);

  /* do partial sum on each proc */
  for (i=0; i<count; i++) PSum += myrow[i];

  /* gather partial sums to the rootginst */
  pvm_gather(PartSums, &PSum, 1, PVM_INT, msgtag=21, gname, rootginst);

  /* do a global sum over myrow, the result goes to rootginst */
  pvm_reduce(PvmSum, myrow, count, PVM_INT, msgtag=23, gname, rootginst);

  /* init values and include location information on each processor */
  midpoint = nprocs/2;
  values[0] = -(myginst - midpoint)*(myginst-midpoint) + count;
  values[1] = myginst;    /* location information */

  /* use a user-defined function in reduce, send answer to rootginst */
  info_user = pvm_reduce(MaxWithLoc, values, 2, PVM_FLOAT, 
                         msgtag=25, gname, rootginst);

  bigN = nprocs*count;
  if (myginst == rootginst)
  {
    /* Complete the Sum of Squares using different methods */
    for (i=0; i<nprocs; i++) Sum1 += PartSums[i]; 
    for (i=0; i<count;  i++) Sum2 += myrow[i];    
    SumSquares = bigN*(bigN+1)*(2*bigN+1)/6;
    if ( (Sum1 == SumSquares) && (Sum2 == SumSquares))
      printf("\n Test OK: Sum of Squares of first %d integers is %d \n",
             bigN, Sum1);
    else
      printf("\n %s%d%s%d%s%d,\n%s%d \n", 
             "ERROR: The Sum of Squares of the first ", bigN, 
             " integers \n was calculated by Sum1 as ", Sum1,
             " and by Sum2 as ", Sum2,
             " for both it should have been ", SumSquares);

    if (info_user < 0) 
      printf(" ERROR: %d on Reduce with User Function\n", info_user);

    if ((values[0] != count) || (values[1] != midpoint)) 
      printf(" ERROR: Should have (%d, %d), but have (%f, %f): \n",
               count, midpoint, values[0], values[1]);
    else
      printf(" Test Ok: Received (%f, %f): ", values[0], values[1]);
    printf("\n");
  }

  /* sync up again, leave group, exit pvm */
  pvm_barrier(gname, nprocs);   
  pvm_lvgroup(gname);
  pvm_exit();
  exit(1);

} /* end main() */


/*
  This function returns the elementwise maximum of two vectors 
  along with location information.
 
  The first num/2 values of x and y are the data values to compare.
  The second num/2 values of x and y are location information
  which is kept with the maximum value determined.

  In the case of a tie in data values, the smaller location 
  is kept to insure the associativity of the operation.
*/

void MaxWithLoc(datatype, x, y, num, info)
int *datatype, *num, *info;
float *x, *y;
{
  int i, count;
  count = (*num) / 2;

  if (*datatype != PVM_FLOAT) { *info = PvmBadParam; return; }

  for (i=0; i<count; i++)
    if (y[i] > x[i])
    {
      x[i]       = y[i];
      x[i+count] = y[i+count];
    }
    else
      if (y[i] == x[i]) x[i+count] = min(x[i+count], y[i+count]);

  *info = PvmOk;
  return;

}  /* end MaxWithLoc() */