root / Pi / C / Pthreads / Pi_Pthreads.c @ 12
Historique | Voir | Annoter | Télécharger (4,51 ko)
1 | 12 | equemene | /******************************************************************************
|
---|---|---|---|
2 | 12 | equemene | * FILE: Pi_Threads
|
3 | 12 | equemene | * Pthreads based on Hello from Blaise Barney, LLNL Tutorial
|
4 | 12 | equemene | * DESCRIPTION:
|
5 | 12 | equemene | * A Pi by Monte Carlo Pthreads program. Demonstrates thread creation and
|
6 | 12 | equemene | * termination.
|
7 | 12 | equemene | * AUTHOR: Emmanuel Quemener from Blaise Barney
|
8 | 12 | equemene | * LAST REVISED: 2013-03-30
|
9 | 12 | equemene | ******************************************************************************/
|
10 | 12 | equemene | |
11 | 12 | equemene | #include <pthread.h> |
12 | 12 | equemene | #include <stdio.h> |
13 | 12 | equemene | #include <stdlib.h> |
14 | 12 | equemene | #include <math.h> |
15 | 12 | equemene | #include <stdio.h> |
16 | 12 | equemene | |
17 | 12 | equemene | #define NUM_THREADS 1024 |
18 | 12 | equemene | |
19 | 12 | equemene | #define ITERATIONS 1000000000 |
20 | 12 | equemene | |
21 | 12 | equemene | #ifdef LONG
|
22 | 12 | equemene | #define LENGTH unsigned long |
23 | 12 | equemene | #else
|
24 | 12 | equemene | #define LENGTH unsigned int |
25 | 12 | equemene | #endif
|
26 | 12 | equemene | |
27 | 12 | equemene | struct thread_data
|
28 | 12 | equemene | { |
29 | 12 | equemene | int thread_id;
|
30 | 12 | equemene | unsigned int seed_w; |
31 | 12 | equemene | unsigned int seed_z; |
32 | 12 | equemene | LENGTH iterations; |
33 | 12 | equemene | LENGTH inside; |
34 | 12 | equemene | }; |
35 | 12 | equemene | |
36 | 12 | equemene | struct thread_data thread_data_array[NUM_THREADS];
|
37 | 12 | equemene | |
38 | 12 | equemene | // Marsaglia RNG very simple implementation
|
39 | 12 | equemene | #define znew ((z=36969*(z&65535)+(z>>16))<<16) |
40 | 12 | equemene | #define wnew ((w=18000*(w&65535)+(w>>16))&65535) |
41 | 12 | equemene | #define MWC (znew+wnew)
|
42 | 12 | equemene | #define SHR3 (jsr=(jsr=(jsr=jsr^(jsr<<17))^(jsr>>13))^(jsr<<5)) |
43 | 12 | equemene | #define CONG (jcong=69069*jcong+1234567) |
44 | 12 | equemene | #define KISS ((MWC^CONG)+SHR3)
|
45 | 12 | equemene | |
46 | 12 | equemene | #define MWCfp MWC * 2.328306435454494e-10f |
47 | 12 | equemene | #define KISSfp KISS * 2.328306435454494e-10f |
48 | 12 | equemene | |
49 | 12 | equemene | LENGTH MainLoopGlobal(LENGTH iterations,unsigned int seed_w,unsigned int seed_z) |
50 | 12 | equemene | { |
51 | 12 | equemene | unsigned int z=seed_z; |
52 | 12 | equemene | unsigned int w=seed_w; |
53 | 12 | equemene | |
54 | 12 | equemene | LENGTH total=0;
|
55 | 12 | equemene | |
56 | 12 | equemene | for (LENGTH i=0;i<iterations;i++) { |
57 | 12 | equemene | |
58 | 12 | equemene | float x=MWCfp ;
|
59 | 12 | equemene | float y=MWCfp ;
|
60 | 12 | equemene | |
61 | 12 | equemene | // Matching test
|
62 | 12 | equemene | LENGTH inside=((x*x+y*y) < 1.0f) ? 1:0; |
63 | 12 | equemene | total+=inside; |
64 | 12 | equemene | } |
65 | 12 | equemene | |
66 | 12 | equemene | return(total);
|
67 | 12 | equemene | |
68 | 12 | equemene | } |
69 | 12 | equemene | |
70 | 12 | equemene | void *MainLoopThread(void *threadarg) |
71 | 12 | equemene | { |
72 | 12 | equemene | int taskid;
|
73 | 12 | equemene | LENGTH iterations,total=0;
|
74 | 12 | equemene | unsigned int z,w; |
75 | 12 | equemene | |
76 | 12 | equemene | struct thread_data *my_data;
|
77 | 12 | equemene | |
78 | 12 | equemene | my_data=(struct thread_data *) threadarg;
|
79 | 12 | equemene | |
80 | 12 | equemene | taskid = my_data->thread_id; |
81 | 12 | equemene | iterations = my_data->iterations; |
82 | 12 | equemene | z = my_data->seed_z; |
83 | 12 | equemene | w = my_data->seed_w; |
84 | 12 | equemene | |
85 | 12 | equemene | printf("\tThread #%i, with seeds (%u,%u) and %lu !\n",
|
86 | 12 | equemene | taskid,z,w,(unsigned long)iterations); |
87 | 12 | equemene | |
88 | 12 | equemene | for (LENGTH i=0;i<iterations;i++) { |
89 | 12 | equemene | |
90 | 12 | equemene | float x=MWCfp ;
|
91 | 12 | equemene | float y=MWCfp ;
|
92 | 12 | equemene | |
93 | 12 | equemene | // Matching test
|
94 | 12 | equemene | LENGTH inside=((x*x+y*y) < 1.0f) ? 1:0; |
95 | 12 | equemene | total+=inside; |
96 | 12 | equemene | } |
97 | 12 | equemene | |
98 | 12 | equemene | my_data->inside=total; |
99 | 12 | equemene | |
100 | 12 | equemene | pthread_exit((void*) my_data);
|
101 | 12 | equemene | } |
102 | 12 | equemene | |
103 | 12 | equemene | int main(int argc, char *argv[]) |
104 | 12 | equemene | { |
105 | 12 | equemene | pthread_t threads[NUM_THREADS]; |
106 | 12 | equemene | pthread_attr_t attr; |
107 | 12 | equemene | int rc, t;
|
108 | 12 | equemene | unsigned int num_threads; |
109 | 12 | equemene | LENGTH iterations,inside=0;
|
110 | 12 | equemene | void *status;
|
111 | 12 | equemene | float pi;
|
112 | 12 | equemene | |
113 | 12 | equemene | if (argc > 1) { |
114 | 12 | equemene | iterations=(LENGTH)atol(argv[1]);
|
115 | 12 | equemene | num_threads=atoi(argv[2]);
|
116 | 12 | equemene | } |
117 | 12 | equemene | else {
|
118 | 12 | equemene | iterations=ITERATIONS; |
119 | 12 | equemene | num_threads=1;
|
120 | 12 | equemene | printf("\n\tPi : Estimate Pi with Monte Carlo exploration\n\n");
|
121 | 12 | equemene | printf("\t\t#1 : number of iterations (default 1 billion)\n");
|
122 | 12 | equemene | printf("\t\t#2 : number of threads (default 1)\n\n");
|
123 | 12 | equemene | } |
124 | 12 | equemene | |
125 | 12 | equemene | printf("\tNumber of threads defined to %u\n",num_threads);
|
126 | 12 | equemene | printf("\tNumber of iterations defined to %lu\n\n",(unsigned long)iterations); |
127 | 12 | equemene | |
128 | 12 | equemene | /* Initialize and set thread detached attribute */
|
129 | 12 | equemene | pthread_attr_init(&attr); |
130 | 12 | equemene | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); |
131 | 12 | equemene | |
132 | 12 | equemene | for(t=0;t<num_threads;t++) { |
133 | 12 | equemene | |
134 | 12 | equemene | thread_data_array[t].thread_id = t; |
135 | 12 | equemene | thread_data_array[t].iterations = iterations/num_threads; |
136 | 12 | equemene | thread_data_array[t].seed_w = (t+1)<<4; |
137 | 12 | equemene | thread_data_array[t].seed_z = (1048576*(t+1))>>4; |
138 | 12 | equemene | thread_data_array[t].inside = 0;
|
139 | 12 | equemene | |
140 | 12 | equemene | printf("\tCreating thread %d\n", t);
|
141 | 12 | equemene | rc = pthread_create(&threads[t], &attr, MainLoopThread, (void *)
|
142 | 12 | equemene | &thread_data_array[t]); |
143 | 12 | equemene | |
144 | 12 | equemene | if (rc) {
|
145 | 12 | equemene | printf("\tERROR; return code from pthread_create() is %d\n", rc);
|
146 | 12 | equemene | exit(-1);
|
147 | 12 | equemene | } |
148 | 12 | equemene | } |
149 | 12 | equemene | |
150 | 12 | equemene | /* Free attribute and wait for the other threads */
|
151 | 12 | equemene | pthread_attr_destroy(&attr); |
152 | 12 | equemene | |
153 | 12 | equemene | for(t=0; t<num_threads; t++) { |
154 | 12 | equemene | rc = pthread_join(threads[t], &status); |
155 | 12 | equemene | if (rc) {
|
156 | 12 | equemene | printf("\tERROR; return code from pthread_join() is %d\n", rc);
|
157 | 12 | equemene | exit(-1);
|
158 | 12 | equemene | } |
159 | 12 | equemene | printf("\tMain: completed join with thread %i having a status of %ld\n",
|
160 | 12 | equemene | t,(long)status);
|
161 | 12 | equemene | } |
162 | 12 | equemene | |
163 | 12 | equemene | for(t=0;t<num_threads;t++) { |
164 | 12 | equemene | printf("\tReturn to main with %i thread, %lu inside\n",
|
165 | 12 | equemene | t,(unsigned long)thread_data_array[t].inside); |
166 | 12 | equemene | inside+=thread_data_array[t].inside; |
167 | 12 | equemene | } |
168 | 12 | equemene | |
169 | 12 | equemene | printf("\tMain: program completed. Exiting.\n\n");
|
170 | 12 | equemene | |
171 | 12 | equemene | pi=4.*(float)inside/(float)iterations; |
172 | 12 | equemene | |
173 | 12 | equemene | printf("\tPi=%f with error %f and %lu iterations\n\n",pi,
|
174 | 12 | equemene | fabs(pi-4*atan(1))/pi,(unsigned long)iterations); |
175 | 12 | equemene | |
176 | 12 | equemene | pthread_exit(NULL);
|
177 | 12 | equemene | } |