source: CIVL/examples/compare/dot/mpithreads_both_weak_scaling.c@ bb03188

main test-branch
Last change on this file since bb03188 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 5.4 KB
Line 
1/*****************************************************************************
2* FILE: mpithreads_both.c
3* DESCRIPTION:
4* This program illustrates the simultaneous use of MPI and Pthreads.
5* It is essentially a simple combination of a code that implements a dot
6* product using threads, and a code that uses MPI for the same purpose.
7* It is the last of four codes used to show the progression from a serial
8* program to a hybrid MPI/Pthreads program. The other relevant codes are:
9* - mpithreads_serial.c - The serial version
10* - mpithreads_threads.c - A shared memory programming model using
11* Pthreads
12* - mpithreads_mpi.c - A distributed memory programming model with MPI
13* All the internode MPI communication is done by the main thread on each
14* node - the other threads within that node need not even be aware that
15* internode communication is being performed. Use of the SPMD model for
16* MPI was chosen for convenience, with replication of the main data on
17* all nodes. A more memory efficient implementation would be advisable
18* for larger data sets. This is the simplest model for mixed MPI/Pthreads
19* programming.
20* SOURCE: Vijay Sonnad, IBM
21* LAST REVISED: 01/29/09 Blaise Barney
22******************************************************************************/
23#include "mpi.h"
24#include <pthread.h>
25#include <stdio.h>
26#include <stdlib.h>
27
28/*
29This structure has been changed slightly from the previous cases
30to include the number of threads per node.
31*/
32
33typedef struct
34 {
35 double *a;
36 double *b;
37 double sum;
38 int veclen;
39 int numthrds;
40 } DOTDATA;
41
42/* Define globally accessible variables and a mutex */
43#ifdef _CIVL
44$input int MAXTHRDS;
45$input int VECLEN;
46$output double _sum;
47#else
48#define MAXTHRDS 8
49#define VECLEN 100
50#endif
51DOTDATA dotstr;
52pthread_t callThd[MAXTHRDS];
53pthread_mutex_t mutexsum;
54
55/*
56The function dotprod has only minor changes from the code
57that used threads or MPI.
58*/
59
60void *dotprod(void *arg)
61{
62
63 /* Define and use local variables for convenience */
64
65 int i, start, end, len, numthrds, myid, sigSize1, sigSize2, max;
66 long mythrd;
67 double mysum, *x, *y;
68
69 /*
70 The number of threads and nodes defines the beginning
71 and ending for the dot product; each thread does work
72 on a vector of length VECLENGTH.
73 */
74
75 mythrd = (int)(arg[0]);
76 sigSize1 = (int)(arg[1]);
77 sigSize2 = (int)(arg[2]);
78 free(arg);
79 MPI_Comm_rank (MPI_COMM_WORLD, &myid);
80
81 numthrds = dotstr.numthrds;
82 len = dotstr.veclen;
83 max = (myid+1)*sigSize1;
84 max = max > len ? len : max;
85 start = myid*sigSize1 + mythrd*sigSize2;
86 start = start > max ? max : start;
87 end = start + sigSize2;
88 end = end > max ? max : end;
89 x = dotstr.a;
90 y = dotstr.b;
91
92 /*
93 Perform the dot product and assign result
94 to the appropriate variable in the structure.
95 */
96
97 mysum = 0;
98 for (i=start; i<end ; i++)
99 {
100 mysum += (x[i] * y[i]);
101 }
102
103 /*
104 Lock a mutex prior to updating the value in the structure, and unlock it
105 upon updating.
106 */
107 pthread_mutex_lock (&mutexsum);
108 printf("Task %d thread %ld adding partial sum of %f to node sum of %f\n",
109 myid, mythrd, mysum, dotstr.sum);
110 dotstr.sum += mysum;
111 pthread_mutex_unlock (&mutexsum);
112
113 pthread_exit((void*)0);
114}
115
116/*
117As before,the main program does very little computation. It creates
118threads on each node and the main thread does all the MPI calls.
119*/
120
121int main(int argc, char* argv[])
122{
123int len=VECLEN, myid, numprocs;
124long i;
125int nump1, numthrds, segSize1, segSize2;
126double *a, *b;
127double nodesum, allsum;
128void *status;
129pthread_attr_t attr;
130
131/* MPI Initialization */
132MPI_Init (&argc, &argv);
133MPI_Comm_size (MPI_COMM_WORLD, &numprocs);
134MPI_Comm_rank (MPI_COMM_WORLD, &myid);
135
136/* Assign storage and initialize values */
137numthrds=MAXTHRDS;
138a = (double*) malloc (len*sizeof(double));
139b = (double*) malloc (len*sizeof(double));
140if (len % numprocs == 0)
141 segSize1 = len / numprocs;
142else
143 segSize1 = len / numprocs + 1;
144if (segSize1 % numthrds == 0)
145 segSize2 = segSize1 / numthrds;
146else
147 segSize2 = segSize1 / numthrds + 1;
148
149for (i=0; i<len; i++) {
150 a[i]=1;
151 b[i]=a[i];
152 }
153
154dotstr.veclen = len;
155dotstr.a = a;
156dotstr.b = b;
157dotstr.sum=0;
158dotstr.numthrds=MAXTHRDS;
159
160/*
161Create thread attribute to specify that the main thread needs
162to join with the threads it creates.
163*/
164pthread_attr_init(&attr );
165pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
166
167/* Create a mutex */
168pthread_mutex_init (&mutexsum, NULL);
169
170/* Create threads within this node to perform the dotproduct */
171for(i=0;i<numthrds;i++) {
172 int* args = (int *)malloc(3 * sizeof(int));
173 args[0] = i;
174 args[1] = segSize1;
175 args[2] = segSize2;
176 pthread_create( &callThd[i], &attr, dotprod, (void*)args);
177 }
178
179/* Release the thread attribute handle as it is no longer needed */
180pthread_attr_destroy(&attr );
181
182/* Wait on the other threads within this node */
183for(i=0;i<numthrds;i++) {
184 pthread_join( callThd[i], &status);
185 }
186
187nodesum = dotstr.sum;
188printf("Task %d node sum is %f\n",myid, nodesum);
189
190/* After the dot product, perform a summation of results on each node */
191MPI_Reduce (&nodesum, &allsum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
192
193if (myid == 0)
194printf ("Done. MPI with threads version: sum = %f \n", allsum);
195#ifdef _CIVL
196 if(myid == 0)
197 _sum=allsum;
198#endif
199
200MPI_Finalize();
201free (a);
202free (b);
203pthread_mutex_destroy(&mutexsum);
204//exit (0);
205}
Note: See TracBrowser for help on using the repository browser.