2012-01-24 2 views
4

pi를 계산하기 위해 몬테카를로 방법을 병렬 처리하는 데 문제가 있습니다.pi 계산의 OpenMP 병렬화가 느리거나 잘못되었습니다.

#pragma omp parallel for private(i,x,y) schedule(static) reduction(+:count) 
    for (i = 0; i < points; i++) { 
    x = rand()/(RAND_MAX+1.0)*2 - 1.0; 
    y = rand()/(RAND_MAX+1.0)*2 - 1.0; 

    // Check if point lies in circle 
    if(x*x + y*y < 1.0) { count++; } 
    } 

문제는 그것이 I가 schedule(static) PI를 사용하는 경우를 과소 평가하고, I는 schedule(dynamic)를 사용하는 경우 일련의 구현보다 느리다 : 여기를위한 루프 parallelised이다. 내가 도대체 ​​뭘 잘못하고있는 겁니까? 다른 문제를 해결하기 위해 (예 : Using OpenMP to calculate the value of PI) 시도했지만 직렬 구현보다 훨씬 느립니다. 사전

+0

'rand()'는 스레드로부터 안전한가요? – Mysticial

+0

@Mystical : 그렇지 않은 것 같습니다 : http://stackoverflow.com/questions/6161322/using-rand-with-multiple-threads-in-c –

+0

나는 @Mysticial이 올바른 생각을 가지고 있다고 생각합니다. 'rand'는 일반적으로 내부 자원을 공유 자원으로 사용하여 모든 호출에서 직렬화를 강제하는 내부 "시드"를 갖습니다. 그렇지 않으면 잘못된 결과가 발생할 위험이 있습니다. 사용 가능한 경우'rand_r' 또는 (선호)'drand48_r'을 대신 사용해보십시오. 또는 C++ 11에 도입 된 난수 생성 클래스를 고려하십시오. 각 인스턴스는 자체 상태를 가지므로 직렬화를 피해야합니다 (그러나 초기화 절차가 까다로울 수 있습니다. 동일한 시퀀스를 만드는 여러 스레드가 거의 효과가 없을 수 있습니다). –

답변

6

당신이, 그 함수가 재진입되지 않았거나 스레드 안전 C 라이브러리 rand 기능을 사용하는 가정에서

감사합니다. POSIX는 rand_r 기능을 제공하지만, (인용하는 glibc는 문서) :

POSIX.1은 멀티 스레드 프로그램에서 재현 난수를 지원하기 위해 C 표준 기능을 확장했다. 그러나 연장은 심하게 설계되어 심각한 작업에는 적합하지 않습니다.

특히, 시드는 좋은 PRNG를위한 비트가 충분하지 않은 부호없는 정수 여야합니다. SVID 난수 함수를 사용하는 것이 좋습니다. 그 중 nrand48_r은 아마도 당신이 찾고있는 것입니다.

또는 다른 라이브러리를 사용할 수도 있습니다.

+0

nrand48_r은 어떻게 사용합니까? 그것은 표준 라이브러리에있는 것으로 보이지 않습니다. 시드가 짧은 부호없는 정수인 nrand48 (& seed)를 사용할 수 있습니다. 하지만 각 스레드마다 다른 시드를 사용하면 여전히 성능이 떨어집니다. – Eddy

1

이러한 작업을 병렬로 수행 할 때 고려해야 할 사항 중 하나는 계산을 수행하는 다양한 방법으로 인해 다른 반올림 오류가 발생할 수 있다는 것입니다.

예 : (A+B)(C+D)와 병렬로 계산 될 것이다

((A+B) + (C+D)) 직렬 방식 (((A+B) + C) + D) 다를 수도있다.