forked from b-k/21st-Century-Examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpthread_factors.c
96 lines (84 loc) · 2.87 KB
/
pthread_factors.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/* Compile with:
export CFLAGS="-g -Wall -O3 --std=c99 -pthread -fopenmp"
make pthread_factors
*/
#include <omp.h> //get_max is still OpenMP
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h> //malloc
#include <string.h> //memset
#include "openmp_getmax.c"
typedef struct {
long int *tally;
int *factor_ct;
int max, thread_ct, this_thread, mutex_ct;
pthread_mutex_t *mutexes;
} tally_s;
void *add_tally(void *vin){
tally_s *in = vin;
for (long int i=in->this_thread; i < in->max; i += in->thread_ct){
int factors = in->factor_ct[i];
pthread_mutex_lock(&in->mutexes[factors % in->mutex_ct]);
in->tally[factors]++;
pthread_mutex_unlock(&in->mutexes[factors % in->mutex_ct]);
}
return NULL;
}
typedef struct {
long int i, max, mutex_ct;
int *factor_ct;
pthread_mutex_t *mutexes ;
} one_factor_s;
void *mark_factors(void *vin){
one_factor_s *in = vin;
long int si = 2*in->i;
for (long int scale=2; si < in->max; scale++, si=scale*in->i) {
pthread_mutex_lock(&in->mutexes[si % in->mutex_ct]);
in->factor_ct[si]++;
pthread_mutex_unlock(&in->mutexes[si % in->mutex_ct]);
}
return NULL;
}
int main(){
long int max = 1e7;
int *factor_ct = malloc(sizeof(int)*max);
int thread_ct = 4, mutex_ct = 128;
pthread_t threads[thread_ct];
pthread_mutex_t mutexes[mutex_ct];
for (long int i=0; i< mutex_ct; i++)
pthread_mutex_init(&mutexes[i], NULL);
factor_ct[0] = 0;
factor_ct[1] = 1;
for (long int i=2; i< max; i++)
factor_ct[i] = 2;
one_factor_s x[thread_ct];
for (long int i=2; i<= max/2; i+=thread_ct){
for (int t=0; t < thread_ct && t+i <= max/2; t++){//extra threads do no harm.
x[t] = (one_factor_s){.i=i+t, .max=max,
.factor_ct=factor_ct, .mutexes=mutexes, .mutex_ct=mutex_ct};
pthread_create(&threads[t], NULL, mark_factors, &x[t]);
}
for (int t=0; t< thread_ct; t++)
pthread_join(threads[t], NULL);
}
FILE *o=fopen("xpt", "w");
for (long int i=0; i < max; i ++){
int factors = factor_ct[i];
fprintf(o, "%i %li\n", factors, i);
}
fclose(o);
int max_factors = get_max(factor_ct, max);
long int tally[max_factors+1];
memset(tally, 0, sizeof(long int)*(max_factors+1));
tally_s thread_info[thread_ct];
for (int i=0; i< thread_ct; i++){
thread_info[i] = (tally_s){.this_thread=i, .thread_ct=thread_ct,
.tally=tally, .max=max, .factor_ct=factor_ct,
.mutexes=mutexes, .mutex_ct =mutex_ct};
pthread_create(&threads[i], NULL, add_tally, &thread_info[i]);
}
for (int t=0; t< thread_ct; t++)
pthread_join(threads[t], NULL);
for (int i=0; i<=max_factors; i++)
printf("%i\t%li\n", i, tally[i]);
}