source: CIVL/examples/pthread/dotprod_mutex.cvl@ 37bfb99

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

Updated examples and pthread.cvh

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

  • Property mode set to 100644
File size: 4.5 KB
Line 
1/*****************************************************************************
2* SOURCE: This is a translation of a Pthread program from the Lawrence Livermore
3* Computing Center POSIX Threads Programming Exercise at:
4* https://computing.llnl.gov/tutorials/pthreads/exercise.html
5* FILE: dotprod_mutex.cvl
6* DESCRIPTION:
7* This example program illustrates the use of mutex variables
8* in a threads program. This version was obtained by modifying the
9* serial version of the program (dotprod_serial.c) which performs a
10* dot product. The main data is made available to all threads through
11* a globally accessible structure. Each thread works on a different
12* part of the data. The main thread waits for all the threads to complete
13* their computations, and then it prints the resulting sum.
14* Command line execution:
15* civl verify -inputNUMTHRDS=4 -inputVECLEN=100000 dotprod_mutex.cvl
16******************************************************************************/
17#include "pthread.cvh"
18#include <civlc.h>
19#include <stdio.h>
20#include <stdlib.h>
21
22/*
23The following structure contains the necessary information
24to allow the function "dotprod" to access its input data and
25place its output into the structure. This structure is
26unchanged from the sequential version.
27*/
28
29typedef struct
30 {
31 double *a;
32 double *b;
33 double sum;
34 int veclen;
35 } DOTDATA;
36
37/* Define globally accessible variables and a mutex */
38
39$input int NUMTHRDS;
40$input int VECLEN;
41 DOTDATA dotstr;
42 pthread_t callThd[NUMTHRDS];
43 pthread_mutex_t mutexsum;
44
45/*
46The function dotprod is activated when the thread is created.
47As before, all input to this routine is obtained from a structure
48of type DOTDATA and all output from this function is written into
49this structure. The benefit of this approach is apparent for the
50multi-threaded program: when a thread is created we pass a single
51argument to the activated function - typically this argument
52is a thread number. All the other information required by the
53function is accessed from the globally accessible structure.
54*/
55
56void *dotprod(void *arg)
57{
58
59/* Define and use local variables for convenience */
60
61 int i, start, end, len ;
62 long offset;
63 double mysum, *x, *y;
64 offset = (long)*arg;
65
66 len = dotstr.veclen;
67 start = offset*len;
68 end = start + len;
69 x = dotstr.a;
70 y = dotstr.b;
71
72/*
73Perform the dot product and assign result
74to the appropriate variable in the structure.
75*/
76 mysum = 0;
77 for (i=start; i<end ; i++)
78 {
79 mysum += (x[i] * y[i]);
80 }
81
82/*
83Lock a mutex prior to updating the value in the shared
84structure, and unlock it upon updating.
85*/
86 pthread_mutex_lock (&mutexsum);
87 dotstr.sum += mysum;
88 printf("Thread %d did %d to %d: mysum=%f global sum=%f\n",offset,start,end,mysum,dotstr.sum); //Removed l from %ld, unsupported
89 pthread_mutex_unlock (&mutexsum);
90
91 pthread_exit(NULL, false, NULL, 0);
92}
93
94/*
95The main program creates threads which do all the work and then
96print out result upon completion. Before creating the threads,
97The input data is created. Since all threads update a shared structure, we
98need a mutex for mutual exclusion. The main thread needs to wait for
99all threads to complete, it waits for each one of the threads. We specify
100a thread attribute value that allow the main thread to join with the
101threads it creates. Note also that we free up handles when they are
102no longer needed.
103*/
104
105int main (void)
106{
107long i;
108long j[NUMTHRDS];
109double *a, *b;
110void *status;
111pthread_attr_t attr;
112
113/* Assign storage and initialize values */
114
115a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
116b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
117
118for (i=0; i<VECLEN*NUMTHRDS; 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<NUMTHRDS;i++)
135 {
136 /* Each thread works on a different set of data.
137 * The offset is specified by 'i'. The size of
138 * the data for each thread is indicated by VECLEN.
139 */
140 j[i] = (long)i;
141 pthread_create(&callThd[i], &attr, dotprod, (void *)&j[i]);
142 }
143
144pthread_attr_destroy(&attr);
145/* Wait on the other threads */
146
147for(i=0;i<NUMTHRDS;i++) {
148 pthread_join(callThd[i], &status);
149 }
150/* After joining, print out the results and cleanup */
151
152printf ("Sum = %f \n", dotstr.sum);
153free (a);
154free (b);
155pthread_mutex_destroy(&mutexsum);
156pthread_exit(NULL, true, NULL, 0);
157}
Note: See TracBrowser for help on using the repository browser.