2012-04-04 105 views
1

所以我一直在使用C編寫一些應用程序並使用OpenMP進行並行化。我實現了Monte-Carlo Pi估計,發現正常的rand()函數並不是重要的,並且是線程安全的。建議使用drand48_r選項。使用drand48_r作爲C中的隨機數生成器

現在,這裏是問題,我的應用程序編譯罰款在Linux例如。 Ubuntu,Fedora和CentOS,但不能在Mac 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編譯的,

gcc simple.c -o simple

+1

請注意,使用'time()'作爲隨機種子不是非常隨機的。這對您的應用程序可能無關緊要,但至少要注意如果兩個進程在同一秒運行,他們將得到相同的隨機數序列,因爲它們使用相同的種子(時間)。 – 2012-04-04 19:47:22

+0

是的,我通常將SEED值與一個線程的ID結合在一起。在這個例子中,爲了簡單起見,我省略了OpenMP代碼。 – pfdevilliers 2012-04-06 09:46:10

回答

4

我實在不明白使用drand48_rerand48的增益。 erand48drand48具有相同類型的隨機發生器,但與接收隨機發生器的狀態作爲函數參數相比,它完美地完成了這項工作。

_r擴展將結果存儲到位(第二個參數)並返回始終保證爲0的錯誤代碼。我沒有看到太多的用處。我會堅持POSIX接口(特別是erand48)。

+0

保證爲0的錯誤代碼的目的是什麼?爲什麼有人會檢查這個代碼,如果它總是一樣的? – 2017-10-16 15:20:44

+0

@ this.lau_,所有很好的問題。你不得不問GNU人他們在想什麼。 – 2017-10-16 15:36:42

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()來實現drand48_r(),或者您可以輕鬆移植並使用POSIX定義的erand48(),並且在大多數Unix系統上自20世紀80年代起可用。就我個人而言,我會考慮可移植性,但編寫一個簡單的drand48_r()也很簡單,除非要整理哪個頭文件來聲明它。