2012-04-04 3 views
1

그래서 C로 일부 응용 프로그램을 작성하고 OpenMP를 사용하여 병렬 처리를 수행했습니다. 몬테카를로 파이 추정치를 구현했는데 정상적인 rand() 함수는 재진입 및 스레드 안전성이 없다는 것을 알았습니다. 권장 사항은 drand48_r 옵션을 사용하는 것입니다.C에서 난수 생성기로 drand48_r 사용

이제 문제가 생겼습니다. 예를 들어, 제 응용 프로그램이 Linux에서 정상적으로 컴파일됩니다. 우분투, 페도라와 CentOS하지만 맥 OS X에서 컴파일되지 않습니다. OS X에서 컴파일 오류가 발생했습니다.

simple.c:7: error: storage size of ‘randBuffer’ isn’t known

간단한 예제로 사용 된 코드는 다음과 같습니다

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char* argv[]) { 

    double x; 
    struct drand48_data randBuffer; 

    srand48_r(time(NULL), &randBuffer); 

    drand48_r(&randBuffer, &x); 

    printf("Random number: %f\n", x); 

    return EXIT_SUCCESS; 
} 

내가 그것에 대해 읽어 내가 여기

These functions are GNU extensions and are not portable.

이 링크입니다, 그 사람이 페이지에 메모를 발견 그것 : http://www.kernel.org/doc/man-pages/online/pages/man3/drand48_r.3.html

나는 많은 질문이있다;

  1. GNU 확장은 무엇이며 이식성을 없게 만드는 요인은 무엇입니까?
  2. 스레드로부터 안전한 OS X에서 난수 생성을 위해 어떤 대안을 사용할 수 있습니까?

글쎄요.

예는

gcc simple.c -o simple

+1

랜덤 시드로'time()'을 사용하는 것은 매우 임의적이지 않습니다. 이것은 응용 프로그램에서는 중요하지 않지만 두 프로세스가 같은 초에 실행될 경우 동일한 시드 (시간)를 사용하기 때문에 동일한 난수 시퀀스를 얻게됩니다. –

+0

예 일반적으로 SEED 값을 스레드 ID와 결합합니다. 이 예제에서 나는 단순화를 위해 OpenMP 코드를 생략했다. – pfdevilliers

답변

4

정말 erand48 이상 drand48_r을 사용하는 이득이 표시되지 않는 등의 gcc로 컴파일. erand48은 랜덤 제네레이터의 타입이 drand48 인 것과 같지만 랜덤 제네레이터의 상태를 함수 파라미터로받는 것과 비교해 완벽하게 작동합니다.

_r 확장은 결과를 제자리에 저장하고 (두 번째 매개 변수) 항상 0이 될 오류 코드를 반환합니다. 나는 이것 모두에서별로 쓸모가 없다. POSIX 인터페이스 (특히 erand48)를 고수 할 것입니다.

+0

0으로 보장되는 오류 코드의 목적은 무엇입니까? 항상 동일하다면 누구든지이 코드를 확인하는 이유는 무엇입니까? –

+0

@ this.lau_, 좋은 질문입니다. GNU 사람들에게 그들이 무엇을 생각하고 있는지 물어보아야 할 것입니다. –

3

<stdlib.h>의 표준 재진입 기능을 사용하십시오. 이들은 유비쿼터스 _r 접미사 단순히 이전 날짜 때문에 이름은 :

#include <stdlib.h> 

double drand48(void); 

double erand48(unsigned short xsubi[3]); 

long jrand48(unsigned short xsubi[3]); 

void lcong48(unsigned short param[7]); 

long lrand48(void); 

long mrand48(void); 

long nrand48(unsigned short xsubi[3]); 

unsigned short *seed48(unsigned short seed16v[3]); 

void srand48(long seedval); 

erand48() 함수 상태로 (실제로, 3 부호 팬티의 어레이) 데이터 구조를 취. 따라서 drand48_r()을 로컬로 정의한 drand48_data 구조체에 번들링하고 drand48_r()erand48()으로 호출하거나 POSIX에 정의 된 erand48()을 사용할 수 있으며 대부분의 유닉스 시스템에서 사용할 수 있습니다. 개인적으로, 나는 이식성에 대해 갈 것이지만 간단한 drand48_r() 작성은 어떤 헤더가 그것을 선언 하는지를 제외하고는 간단하다.