2012-04-04 57 views
1

私はC言語でいくつかのアプリケーションを書いており、並列化のためにOpenMPを使っています。私はMonte-Carlo Pi推定を実装し、通常のrand()関数はリエントレントでスレッドセーフではないことを発見しました。 drand48_rオプションを使用することをお勧めします。C言語の乱数生成器としてdrand48_rを使用

ここに問題があります。私のアプリケーションは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.

がリンクであること、manページにノートを見つけましたそれには: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()'を使うことはあまりランダムではないことに注意してください。これはアプリケーションにとって重要ではないかもしれませんが、2つのプロセスが同じ秒で実行される場合、同じシード(時間)を使用するため、乱数の同じシーケンスが得られます。 –

+0

ええ、私は通常、SEEDの値をスレッドのIDと組み合わせます。この例では、わかりやすくするためにOpenMPコードを省略しました。 – pfdevilliers

答えて

4

私は本当にerand48drand48_rを使用してのゲインが表示されない、などのgccでコンパイルされています。 erand48は、drand48と同じタイプのランダムジェネレータを持っていますが、ランダムジェネレータの状態をファンクションパラメータとして受け取るのと比較して、完全にそのジョブを行います。

_r拡張子は結果を格納し(2番目のパラメータ)、常に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つの符号なしshortの配列)は、データ構造をとります。したがって、ローカルで定義されたdrand48_data構造体にそれを束ねてdrand48_r()erand48()と呼ぶか、POSIXで定義されているerand48()を使用して、ほとんどのUnixシステムで利用可能になっています。個人的には移植性を考えていますが、単純なdrand48_r()の記述は、どのヘッダーがそれを宣言するかを並べ替える以外は簡単です。