/* Compile with: export CFLAGS="-g -Wall -O3 --std=c99 -pthread -fopenmp" make pthread_factors */ #include //get_max is still OpenMP #include #include #include //malloc #include //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]); }