Я пишу простое приложение для сравнительного анализа для оценки / сравнения производительности многопоточности pthreads и OpenMP. Для этого я использую метод Монте-Карло для вычисления числа Пи, распределяя итерации по нескольким потокам.
Я написал небольшой и простой класс-оболочку для интерфейса pthreads, который просто создает поток при создании объекта и сохраняет идентификатор потока.
Теперь по моей проблеме: я обнаружил, что если я порождаю более одного потока, кажется, что цикл for внутри этого потока не выполняется. Я проверил это, увеличив переменную внутри цикла, которая остается нулевой для всех, кроме последнего потока. Как ни странно, это происходит не при каждом запуске программы.
Добавление задержки между созданием потоков устраняет проблему, но я действительно не понимаю, почему.
void* monteCarlo_intern(void* args){
struct thread_arguments* arguments = (struct thread_arguments*) args;
long unsigned int total=0;
long unsigned int inside=0;
thread_local std::mt19937_64 generator(std::random_device{}());
thread_local std::uniform_real_distribution<double> distribution(0.0, 1.0);
double d1 = 0, d2 = 0;
for(total = 0; total < arguments -> iterations; total++) {
d1 = distribution(generator);
d2 = distribution(generator);
if((d1*d1 + d2*d2) <= 1.0) {inside++;}
}
*arguments->inside = inside * 4;
}
double calcPI_monteCarlo(struct for_arguments args_in){
std::vector <long unsigned int> inside_vec(args_in.no_threads - 1, 0); //Vector to hold results per thread
std::vector<Thread> threads; //Vector to hold threads
const unsigned long int iters_per_t = args_in.iterations / args_in.no_threads;
std::vector<thread_arguments> args(args_in.no_threads - 1, {NULL, iters_per_t});
for (unsigned int i = 0; i < args_in.no_threads - 1; i++)
{
args[i].inside = &inside_vec[i]; //Assign results-vector adress to thread to capture result
threads.emplace_back(monteCarlo_intern, &args[i]); //Create thread and store it in vector
}
long unsigned int inside = 0;
thread_arguments local_args = {&inside, iters_per_t};
monteCarlo_intern(&local_args); //Do the same calculation locally to reduce number of spawned threads
for (unsigned int i = 0; i < args_in.no_threads - 1; i++)
{
pthread_join(threads[i].get_id(), NULL);
inside += inside_vec[i];
}
long unsigned int total = iters_per_t * args_in.no_threads;
return (double)inside / total;
}