#include #include #include #include #include #define N_THREADS 5 #define N_STEPS 200 #define N_NUMBERS_CALCULATED 10000 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; pthread_spinlock_t alive_threads_lock; pthread_spinlock_t produced_numbers_lock; int amicable_numbers[N_NUMBERS_CALCULATED]; long produced = 0; int threads_alive = 0; int calculate_amicable_number(int number) { for(int i=1; i< number; i++){ if(number % i == 0){ number = number + i; } } return number; } void *calculate_amicable_number_invterval(void * arg) { int start = *((int *)arg); int calculated = 0; int h = 0; for(int i = 0; i < N_STEPS; i++){ calculated = calculate_amicable_number(start + i); h++; if (start + i < N_NUMBERS_CALCULATED) { amicable_numbers[start +i] = calculated; } else { pthread_spin_lock(&alive_threads_lock); threads_alive--; printf("My thread start was: %d and I calculated %d numbers\n", start, h); pthread_spin_unlock(&alive_threads_lock); free(arg); return NULL; } } pthread_spin_lock(&alive_threads_lock); threads_alive--; pthread_spin_unlock(&alive_threads_lock); printf("my thread start was: %d and i calculated %d numbers\n", start, h); free(arg); return NULL; } int not_all_numbers_calculated() { int ret = 0; pthread_spin_lock(&produced_numbers_lock); if(produced < N_NUMBERS_CALCULATED) ret = 1; pthread_spin_unlock(&produced_numbers_lock); return ret; } int is_there_space_for_new_thread() { int ret = 0; pthread_spin_lock(&alive_threads_lock); if (threads_alive < N_THREADS) ret = 1; pthread_spin_unlock(&alive_threads_lock); return ret; } int main() { pthread_spin_init(&alive_threads_lock, PTHREAD_PROCESS_PRIVATE); pthread_spin_init(&produced_numbers_lock, PTHREAD_PROCESS_PRIVATE); pthread_t thread; double dt = omp_get_wtime(); while(not_all_numbers_calculated()){ if(is_there_space_for_new_thread()) { int *arg = malloc(sizeof(*arg)); pthread_spin_lock(&produced_numbers_lock); *arg = produced; pthread_spin_unlock(&produced_numbers_lock); pthread_create(&thread, NULL, calculate_amicable_number_invterval,(void *) arg); pthread_spin_lock(&alive_threads_lock); threads_alive += 1; pthread_spin_unlock(&alive_threads_lock); pthread_spin_lock(&produced_numbers_lock); produced += N_STEPS; pthread_spin_unlock(&produced_numbers_lock); } } dt = omp_get_wtime() - dt; sleep(1); printf("Sleeping 2 seconds, waiting for all threads to finish\n"); for(int i = 0; i < N_NUMBERS_CALCULATED; i++){ printf("%d, ", amicable_numbers[i]); } printf("\nExecution time: %lf\n", dt); return 0; /// 10 000 korakov /// 1 THREAD: 27.789431 /// 2 THREADS: 11.234548, speedup: 2.473569119113648 /// 4 THREADS: 4.232311, speedup: 6.566018187226789 /// 8 THREADS: 1.551455, speedup: 17.91185113329101 /// 16 THREADS: 0.605447, speedup: 45.899031624568295 }