내가 스레드 안전 기능스레드 안전 병렬 RNG()
rand_r
와 파이의 계산이 버전을 사용하지만이를 실행할 때 느린 것 같습니다 (그리고 대답은 잘못된 것입니다) 프로그램은 병렬 처리 프로그램과 비교하여 순차 프로그램과 비교하여 스레드 안전성을 보장하지 못한다. 이 사용 방법은 스레드로부터 안전하지 않은 것으로 보입니다. 그러나 나는 thread-safe PRNG에 관한 많은 질문을 읽고 rand_r이 충분히 안전해야한다는 것을 배웠기 때문에 그 이유를 알지 못합니다.
#include <iostream>
#include <random>
#include <ctime>
#include "omp.h"
#include <stdlib.h>
using namespace std;
unsigned seed;
int main()
{
double start = time(0);
int i, n, N;
double x, y;
N = 1<<30;
n = 0;
double pi;
#pragma omp threadprivate(seed)
#pragma omp parallel private(x, y) reduction(+:n)
{
for (i = 0; i < N; i++) {
seed = 25234 + 17 * omp_get_thread_num();
x = rand_r(&seed)/(double) RAND_MAX;
y = rand_r(&seed)/(double) RAND_MAX;
if (x*x + y*y <= 1)
n++;
}
}
pi = 4. * n/(double) (N);
cout << pi << endl;
double stop = time(0);
cout << (stop - start) << endl;
return 0;
}
P. 그건 그렇고, 마법의 숫자는 무엇입니까
seed = 25234 + 17 * omp_get_thread_num();
? 나는 그 (것)들을 어떤 대답에서 훔쳤다.
편집 : Gilles의 의견은 나를 도왔습니다. 해결 방법은 다음과 같습니다. 1. for 루프 및 시드 초기화 행을 전환하려면. 2.
수정 된 코드의 #pragma OMP를 추가하려면 문제가 해결
#pragma omp parallel private(x, y, seed)
{
seed = 25234 + 17 * omp_get_thread_num();
#pragma omp for reduction(+:n)
for (int i = 0; i < N; i++) {
x = (double) rand_r(&seed)/(double) RAND_MAX;
y = (double) rand_r(&seed)/(double) RAND_MAX;
if (x*x + y*y <= 1)
n++;
}
}
을 읽습니다.
대답은 무엇을 의미합니까? rand_r이 각 스레드에 대해 별도의 시퀀스를 지원할 것으로 기대하십니까? 확실히, 그러한 시퀀스 중 하나 이상은 같은 생성자의 단일 스레드 호출과 일치하지 않습니다. 두 개의 쓰레드가 동일한 순서로 떨어지면 true PRNG가 "잘못된"것으로 간주되지만 비 병렬 생성기를 사용하여 단축키를 사용할 경우에는 그런 보증이 없습니다. – tim18
@ tim18 "answer is wrong"Pi의 결과 값이 3.14가 아니지만 (rand()가있는 순차 프로그램을 사용할 때 3.14). 예, 스레드 수에 따라 시드를 사용하기 때문에 각 스레드마다 별도의 시퀀스가 필요합니다. 아니면 무언가를 놓치고 있습니까? ... – newt
네가 뭔가를 놓친다. 루프의 각 반복에서 씨앗을 초기화하지 말고 한 번만. 당신이 ATM을하는 방식으로, 당신은 계속해서 똑같은 "무작위"번호를 반복 생성 할 것입니다. – Gilles