source: CIVL/examples/pthread/dotprod_mutex.cvl@ 761eb6f

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

Updated examples and Makefile

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

  • Property mode set to 100644
File size: 4.4 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((void*) 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;
108double *a, *b;
109void *status;
110pthread_attr_t attr;
111
112/* Assign storage and initialize values */
113
114a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
115b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
116
117for (i=0; i<VECLEN*NUMTHRDS; i++) {
118 a[i]=1;
119 b[i]=a[i];
120 }
121
122dotstr.veclen = VECLEN;
123dotstr.a = a;
124dotstr.b = b;
125dotstr.sum=0;
126
127pthread_mutex_init(&mutexsum, NULL);
128
129/* Create threads to perform the dotproduct */
130pthread_attr_init(&attr);
131pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
132
133for(i=0;i<NUMTHRDS;i++)
134 {
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/* Wait on the other threads */
144
145for(i=0;i<NUMTHRDS;i++) {
146 pthread_join(callThd[i], &status);
147 }
148/* After joining, print out the results and cleanup */
149
150printf ("Sum = %f \n", dotstr.sum);
151free (a);
152free (b);
153pthread_mutex_destroy(&mutexsum);
154pthread_exit(NULL);
155}
Note: See TracBrowser for help on using the repository browser.