Следующая программа по существу такая же, как описанная here. Когда я бегу и компилировать программу с помощью двух потоков (NTHREADS == 2), я получаю следующий раз запустите:Многопоточность random_r медленнее, чем однопоточная версия
real 0m14.120s
user 0m25.570s
sys 0m0.050s
Когда он запускается только один поток (NTHREADS == 1), я задавят раз значительно лучше, хотя он использует только одно ядро.
real 0m4.705s
user 0m4.660s
sys 0m0.010s
Моя система двухъядерный, и я знаю, что random_r является поточно, и я уверен, что это не является блокирующим. Когда одна и та же программа запускается без random_r, и вычисление косинусов и синусов используется в качестве замены, двухпоточная версия работает примерно в 1/2 раза, как ожидалось.
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define NTHREADS 2
#define PRNG_BUFSZ 8
#define ITERATIONS 1000000000
void* thread_run(void* arg) {
int r1, i, totalIterations = ITERATIONS/NTHREADS;
for (i = 0; i < totalIterations; i++){
random_r((struct random_data*)arg, &r1);
}
printf("%i\n", r1);
}
int main(int argc, char** argv) {
struct random_data* rand_states = (struct random_data*)calloc(NTHREADS, sizeof(struct random_data));
char* rand_statebufs = (char*)calloc(NTHREADS, PRNG_BUFSZ);
pthread_t* thread_ids;
int t = 0;
thread_ids = (pthread_t*)calloc(NTHREADS, sizeof(pthread_t));
/* create threads */
for (t = 0; t < NTHREADS; t++) {
initstate_r(random(), &rand_statebufs[t], PRNG_BUFSZ, &rand_states[t]);
pthread_create(&thread_ids[t], NULL, &thread_run, &rand_states[t]);
}
for (t = 0; t < NTHREADS; t++) {
pthread_join(thread_ids[t], NULL);
}
free(thread_ids);
free(rand_states);
free(rand_statebufs);
}
Я смущен, почему при генерации случайных чисел два резьбовых версия работает намного хуже, чем однотридовая версия, с учетом random_r предназначен для использования в многопоточных приложениях.
Ugh. Это может укусить практически любую небольшую плотную структуру, которую несколько потоков попытаются написать на части, не так ли? –
Спасибо за помощь, я бы никогда не подумал об этом. Пс. Я переместил rand_states и rand_statebufs в поток и только что инициализировал генератор случайных чисел. Что также прекрасно решает проблему кеша очень простым способом. – Nixuz
@ Николас: Да. Он платит, чтобы не быть чрезмерным с памятью. Имейте в виду, что упаковка ваших локальных распределений потоков также может помочь. Местные жители нитей могут быть колоссальной победой, когда все сделано правильно, так как вы можете избежать так много конфликтов и блокировки кеша. –