source: CIVL/examples/pthread/mpithreads_threads.cvl@ 4b4bbb3

1.23 2.0 main test-branch
Last change on this file since 4b4bbb3 was 38374b7, checked in by John Edenhofner <johneden@…>, 12 years ago

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

  • Property mode set to 100644
File size: 4.6 KB
RevLine 
[38374b7]1/*****************************************************************************
2* FILE: mpithreads_threads.c
3* DESCRIPTION:
4* This simple program illustrates the use of Pthreads in a program obtained
5* by modifying a serial code that performs a dot product. It is the second
6* of four codes used to show the progression from a serial program to a
7* hybrid MPI/Pthreads program. The other relevant codes are:
8* - mpithreads_serial.c - The serial version
9* - mpithreads_mpi.c - A distributed memory programming model with MPI
10* - mpithreads_both.c - A hybrid model that utilizes both MPI and
11* Pthreads to execute on systems that are comprised of clusters
12* of SMP's.
13* The main data is made available to all threads through a globally
14* accessible structure. Each thread works on a different part of the
15* data. The main thread waits for all the threads to complete their
16* computations, and then it prints the resulting sum.
17* SOURCE: Vijay Sonnad, IBM
18* LAST REVISED: 01/29/09 Blaise Barney
19******************************************************************************/
20#include "pthread.cvh"
21#include <civlc.h>
22#include <stdio.h>
23#include <stdlib.h>
24
25/*
26The following structure contains the necessary information to allow the
27function "dotprod" to access its input data and place its output into
28the structure. This structure is unchanged from the sequential version.
29*/
30
31typedef struct
32 {
33 double *a;
34 double *b;
35 double sum;
36 int veclen;
37 } DOTDATA;
38
39/* Define globally accessible variables and a mutex */
40
41#define MAXTHRDS 8
42#define VECLEN 100
43DOTDATA dotstr;
44pthread_t callThd[MAXTHRDS];
45pthread_mutex_t mutexsum;
46
47/*
48The function dotprod is activated when the thread is created. As before,
49all input to this routine is obtained from a structure of type DOTDATA and
50all output from this function is written into this structure. The benefit
51of this approach is apparent for the multi-threaded program: when a thread
52is created we pass a single argument to the activated function - typically
53this argument is a thread number. All the other information required by the
54function is accessed from the globally accessible structure.
55*/
56
57void *dotprod(void *arg)
58{
59
60 /* Define and use local variables for convenience */
61
62 int i, start, end, len ;
63 long offset;
64 double mysum, *x, *y;
65 offset = (long)arg;
66
67 len = dotstr.veclen;
68 start = offset*len;
69 end = start + len;
70 x = dotstr.a;
71 y = dotstr.b;
72
73 /*
74 Perform the dot product and assign result to the appropriate variable in
75 the structure.
76 */
77
78 mysum = 0;
79 for (i=start; i<end ; i++)
80 {
81 mysum += (x[i] * y[i]);
82 }
83
84 /*
85 Lock a mutex prior to updating the value in the shared structure, and
86 unlock it upon updating.
87 */
88 pthread_mutex_lock (&mutexsum);
89 printf("Thread %ld adding partial sum of %f to global sum of %f\n",
90 arg, mysum, dotstr.sum);
91 dotstr.sum += mysum;
92 pthread_mutex_unlock (&mutexsum);
93
94 pthread_exit((void*) 0);
95}
96
97/*
98The main program creates threads which do all the work and then print out
99result upon completion. Before creating the threads, the input data is
100created. Since all threads update a shared structure, we need a mutex for
101mutual exclusion. The main thread needs to wait for all threads to complete,
102it waits for each one of the threads. We specify a thread attribute value
103that allow the main thread to join with the threads it creates. Note also
104that we free up handles when they are no longer needed.
105*/
106
107int main (int argc, char *argv[])
108{
109long i;
110double *a, *b;
111void *status;
112pthread_attr_t attr;
113
114/* Assign storage and initialize values */
115a = (double*) malloc (MAXTHRDS*VECLEN*sizeof(double));
116b = (double*) malloc (MAXTHRDS*VECLEN*sizeof(double));
117
118for (i=0; i<VECLEN*MAXTHRDS; i++) {
119 a[i]=1;
120 b[i]=a[i];
121 }
122
123dotstr.veclen = VECLEN;
124dotstr.a = a;
125dotstr.b = b;
126dotstr.sum=0;
127
128pthread_mutex_init(&mutexsum, NULL);
129
130/* Create threads to perform the dotproduct */
131pthread_attr_init(&attr);
132pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
133
134for(i=0;i<MAXTHRDS;i++) {
135 /* Each thread works on a different set of data.
136 The offset is specified by 'i'. The size of
137 the data for each thread is indicated by VECLEN.
138 */
139 pthread_create( &callThd[i], &attr, dotprod, (void *)i);
140 }
141
142pthread_attr_destroy(&attr);
143
144/* Wait on the other threads */
145for(i=0;i<MAXTHRDS;i++) {
146 pthread_join( callThd[i], &status);
147 }
148
149/* After joining, print out the results and cleanup */
150printf ("Done. Threaded version: sum = %f \n", dotstr.sum);
151free (a);
152free (b);
153pthread_mutex_destroy(&mutexsum);
154pthread_exit(NULL);
155}
156
157
Note: See TracBrowser for help on using the repository browser.