/* prime_counter_better_load.c * This is a threaded counter of prime numbers * It balances the load across threads by giving each thread a series of 100-number sequences, e.g. * if there are two threads, then they will take every other sequence o 100 numbers (T0 gets 0-99, 200-299, etc. while * T1 gets 100-199, 300-399, etc.) * * gcc -o pcb -lpthread prime_counter_better_load.c my_timing.c */ #include #include #include #include "my_timing.h" typedef struct { int id; int start; int N; int big_stride; int small_extent; int count; } ThreadInfo; // check whether a number is a prime // return 1 if it is a prime, else 0 int is_prime (int n) { if (n < 2) return 0; if (n == 2) return 1; if (n%2 == 0) return 0; for (int i = 3; i < n; i += 2) { if (n%i == 0) return 0; } return 1; } // worker func: check the primes in // the given range void *thread_count_primes (void *thread_info) { double t1 = get_time_sec(); ThreadInfo *ti = (ThreadInfo *)thread_info; // do the small_extent numbers every big stride for (int i = ti->start; i < ti->N; i = i + ti->big_stride) { for (int j = 0; j < ti->small_extent; j++) { if (is_prime(i+j)) ti->count++; } } double t2 = get_time_sec(); printf( "Thread %d took %f seconds\n", ti->id, t2-t1 ); pthread_exit(NULL); } int main (int argc, char** argv) { int N = 1000000; int NUM_THREADS = 3; if (argc > 1) NUM_THREADS = atoi(argv[1]); double t1, t2; ThreadInfo srt[NUM_THREADS]; pthread_t thread[NUM_THREADS]; int small_extent = 100; int big_stride = NUM_THREADS * small_extent; for (int i = 0; i < NUM_THREADS; i++) { srt[i].id = i; srt[i].start = i*small_extent; srt[i].N = N; srt[i].big_stride = big_stride; srt[i].small_extent = small_extent; srt[i].count = 0; } t1 = get_time_sec(); // create threads for (int i = 0; i < NUM_THREADS; i++) { pthread_create(&thread[i], NULL, thread_count_primes, &srt[i]); } // join threads for (int i = 0; i < NUM_THREADS; i++) { pthread_join(thread[i], NULL); } // sum counts int count = 0; for (int i = 0; i < NUM_THREADS; i++) { count += srt[i].count; } t2 = get_time_sec(); printf("There are %d primes not larger than %d\n",count, N); printf("It took %f seconds to count the number with %d threads\n", t2 - t1, NUM_THREADS); /* ThreadInfo ti[3]; pthread_t thread[3]; // use 2 of the threads to count N numbers ti[0].start = 0; ti[0].extent = N/2; ti[0].count = 0; ti[1].start = N/2; ti[1].extent = N/2; ti[1].count = 0; ti[2].start = 0; ti[2].extent = N; ti[2].count = 0; t1 = get_time_sec(); // create threads for (int i = 0; i < 2; i++) { pthread_create(&thread[i], NULL, thread_count_primes, &ti[i]); } // join threads for (int i = 0; i < 2; i++) { pthread_join(thread[i], NULL); } // sum counts int count = 0; for (int i = 0; i < 2; i++) { count += ti[i].count; } t2 = get_time_sec(); printf("There are %d primes not larger than 100000\n",count); printf("It took %f seconds to count the number with 2 threads\n", t2 - t1); t1 = get_time_sec(); // create thread pthread_create(&thread[2], NULL, thread_count_primes, &ti[2]); // join thread pthread_join(thread[2], NULL); // sum count count = ti[2].count; t2 = get_time_sec(); printf("There are %d primes not larger than 100000\n",count); printf("It took %f seconds to count the number with 1 thread\n", t2 - t1); */ return EXIT_SUCCESS; }