/* File: pi-pthread.c * * Purpose: Estimates pi in parallel using the Madhava–Leibniz series and * pthreads. NOTE: the number of intervals should be * evenly-divisible by the number of threads. * * Compile: gcc -g -Wall -pthread -o pi-pthread pi-pthread.c * (add -DDEBUG to see thread info) * (bonus: try with -O3 ?) * Run: ./pi-pthread intervals [num-threads] */ #include #include #include #include #include #include /* We define pi here so we can check and see how accurate our computation is. */ #define PI 3.141592653589793238462643 /** Size of the calculation performed by each thread: */ unsigned long long block_size; long num_threads = 1; long double *totals; double get_time(void) { struct timeval t; gettimeofday(&t, NULL); return t.tv_sec + t.tv_usec / 1000000.0; } void *worker_thread(void *arg) { unsigned long rank = (unsigned long) arg; unsigned long long start = block_size * rank; unsigned long long end = block_size * rank + block_size; #ifdef DEBUG fprintf(stderr, "I am thread %ld calculating range %Ld to %Ld\n", (long) rank, start, end); #endif for (unsigned long long i = start; i < end; ++i) { if (i % 2 == 0) { totals[rank] = totals[rank] + (1.0 / ((2.0 * i) + 1)); } else { totals[rank] = totals[rank] - (1.0 / ((2.0 * i) + 1)); } } return NULL; } int main(int argc, char *argv[]) { if (argc <= 1) { fprintf(stderr, "Usage: %s num-intervals [num-threads]\n", argv[0]); return EXIT_FAILURE; } if (argc < 3) { num_threads = sysconf(_SC_NPROCESSORS_ONLN); } else if (argc >= 3) { num_threads = strtol(argv[2], NULL, 10); } unsigned long long intervals = strtoull(argv[1], NULL, 10); printf("Intervals: %llu\n", intervals); printf(" Threads: %ld\n", num_threads); if (intervals == 0 || num_threads <= 0) { return 0; } block_size = intervals / num_threads; double time1 = get_time(); totals = malloc(num_threads * sizeof(long double)); pthread_t *threads = malloc(num_threads * sizeof(pthread_t)); for (int i = 0; i < num_threads; ++i) { pthread_create( &threads[i], NULL, worker_thread, ((void *) (unsigned long) i)); } long double total = 0.0; for (int i = 0; i < num_threads; ++i) { pthread_join(threads[i], NULL); total += totals[i]; } total = total * 4; double time2 = get_time(); printf(" Result: %.20Lf\n", total); printf(" Accuracy: %.20Lf\n", PI - total); printf(" Time: %.10lf\n", time2 - time1); }