Проблема возникает из-за использования rand()
.rand()
является не потокобезопасным.Причина в том, что он использует общее состояние для всех вызовов и поэтому чувствителен к гонкам. Использование stdlib's rand () из нескольких потоков
Есть поточно-безопасный генератор случайных чисел, который называется rand_r()
.Вместо того, чтобы хранить состояние генератора случайных изменений в скрытой глобальной переменной, состояние является параметром функции и может быть преобразовано в локальный поток.
Вы можете использовать его вот так
float rand_generator_r(float a,unsigned int *state )
{
//srand((unsigned int)time(NULL));
return ((float)rand_r(state)/(float)(RAND_MAX)) * a;
}
В параллельном блоке добавьте:
unsigned int rand_state=id*time(NULL); // or whatever thread dependent seed
и в коде вызовите
float x=rand_generator(3.14,&rand_state);
и это должно работать.
Кстати, у меня сложилось впечатление, что в вашем коде есть ложное совместное использование , которое должно замедлять работу.
float sum[NUM_THREADS];
Он модифицируется всеми потоками и действительно может храниться в одной строке кэша. Каждое хранилище (и к нему имеется много хранилищ) создаст недействительное значение во всех других кешах, и это может значительно замедлить вашу производительность.
Вы должны убедиться, что значения находятся в разных кешахстроки с:
#define CACHE_LINE_SIZE 64
struct {
float s;
char padding[CACHE_LINE_SIZE - sizeof(float)];
} sum_nofalse_sharing[NUM_THREADS];
и в вашем коде накапливаются в sum_nofalse_sharing[id].s
В качестве альтернативы, создайте локальную сумму в параллельном блоке и запишите ее значение в сумму [id] в конце.