2022-11-07 18:27:27 +01:00
|
|
|
#include<stdio.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <omp.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2022-11-07 18:56:40 +01:00
|
|
|
#define N_THREADS 16
|
|
|
|
#define N_STEPS 100
|
2022-11-07 18:27:27 +01:00
|
|
|
#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--;
|
|
|
|
pthread_spin_unlock(&alive_threads_lock);
|
|
|
|
free(arg);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_spin_lock(&alive_threads_lock);
|
|
|
|
threads_alive--;
|
|
|
|
pthread_spin_unlock(&alive_threads_lock);
|
|
|
|
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);
|
2022-11-07 18:56:40 +01:00
|
|
|
pthread_t t[N_THREADS];
|
2022-11-07 18:27:27 +01:00
|
|
|
|
|
|
|
double dt = omp_get_wtime();
|
|
|
|
|
|
|
|
while(not_all_numbers_calculated()){
|
|
|
|
|
2022-11-07 18:56:40 +01:00
|
|
|
|
|
|
|
for (int i = 0; i<N_THREADS; i++) {
|
2022-11-07 18:27:27 +01:00
|
|
|
int *arg = malloc(sizeof(*arg));
|
|
|
|
pthread_spin_lock(&produced_numbers_lock);
|
|
|
|
*arg = produced;
|
|
|
|
pthread_spin_unlock(&produced_numbers_lock);
|
2022-11-07 18:56:40 +01:00
|
|
|
pthread_create(&t[i], NULL, calculate_amicable_number_invterval,(void *) arg);
|
2022-11-07 18:27:27 +01:00
|
|
|
pthread_spin_lock(&produced_numbers_lock);
|
|
|
|
produced += N_STEPS;
|
|
|
|
pthread_spin_unlock(&produced_numbers_lock);
|
|
|
|
}
|
2022-11-07 18:56:40 +01:00
|
|
|
|
|
|
|
for (int i = 0; i<N_THREADS; i++)
|
|
|
|
pthread_join(t[i], NULL);
|
2022-11-07 18:27:27 +01:00
|
|
|
}
|
|
|
|
dt = omp_get_wtime() - dt;
|
|
|
|
|
|
|
|
printf("\nExecution time: %lf\n", dt);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/// 10 000 korakov
|
2022-11-07 18:56:40 +01:00
|
|
|
/// 1 THREAD: 14.294979
|
2022-11-07 21:42:44 +01:00
|
|
|
/// 2 THREADS: 11.441722, speedup: 1.2493730401769942
|
|
|
|
/// 4 THREADS: 9.474156, speedup: 1.5088393098023718
|
|
|
|
/// 8 THREADS: 7.467914, speedup: 1.9141863444062155
|
|
|
|
/// 16 THREADS: 3.413084, speedup: 4.1882880702613825
|
2022-11-07 18:27:27 +01:00
|
|
|
|
|
|
|
}
|