简体   繁体   English

在 C 中使用 drand48_r 作为随机数生成器

[英]Using drand48_r as random number generator in C

So i've been writing some applications in C and using OpenMP for parallelization.所以我一直在 C 中编写一些应用程序并使用 OpenMP 进行并行化。 I implemented a Monte-Carlo Pi estimate and found that the normal rand() function is not reentrent and thread-safe.我实施了 Monte-Carlo Pi 估计,发现正常的 rand() function 不是可重入的和线程安全的。 The recommendation is to use the drand48_r option.建议使用 drand48_r 选项。

Now here is the problem, my application compiles fine on Linux eg.现在问题来了,我的应用程序可以在 Linux 上正常编译,例如。 Ubuntu, Fedora and CentOS but does not compile on Mac OS X. The compile error on OS X is. Ubuntu、Fedora 和 CentOS 但在 Mac OS X 上无法编译。OS X 上的编译错误是。

simple.c:7: error: storage size of 'randBuffer' isn't known simple.c:7: 错误:'randBuffer' 的存储大小未知

The code used as the simple example is:用作简单示例的代码是:

#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;
}

I read up about it and I found a note in the man pages that,我阅读了相关内容,并在手册页中发现了一条注释,

These functions are GNU extensions and are not portable.这些函数是 GNU 扩展,不可移植。

Here is a link to it: http://www.kernel.org/doc/man-pages/online/pages/man3/drand48_r.3.html这是它的链接: http://www.kernel.org/doc/man-pages/online/pages/man3/drand48_r.3.html

So I have a number of questions;所以我有很多问题;

  1. What are GNU extensions and what makes it non portable?什么是 GNU 扩展,是什么让它不可移植?
  2. What alternatives do I have for random number generation on OS X that is also thread-safe?对于线程安全的 OS X 上的随机数生成,我有哪些替代方案?

Well that is about it.好吧,就是这样。

The example is compiled with gcc as,该示例使用 gcc 编译为,

gcc simple.c -o simple gcc 简单。c -o 简单

I don't really see the gain of using drand48_r over erand48 .我真的没有看到使用drand48_r而不是erand48的好处。 erand48 has the same type of random generator as drand48 but compared to that receives the state of the random generator as a function parameter, so it perfectly does the job. erand48具有与drand48相同类型的随机生成器,但相比之下,它接收随机生成器的 state 作为 function 参数,因此它完美地完成了这项工作。

The _r extensions store the result in place (the second parameter) and return an error code that is always guaranteed to be 0 . _r扩展将结果存储在适当的位置(第二个参数)并返回一个始终保证为0的错误代码。 I don't see much use in all of this.我看不出这一切有多大用处。 I'd stick to the POSIX interfaces (in particular erand48 ).我会坚持使用 POSIX 接口(特别是erand48 )。

Use the standard re-entrant functions from <stdlib.h> .使用<stdlib.h>中的标准可重入函数。 They simply pre-date the ubiquitous _r suffix, so their names are:它们只是早于无处不在的_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);

The erand48() function takes a data structure (actually, an array of 3 unsigned shorts) as its state. So, you can implement drand48_r() for Mac OS X by bundling that into a locally defined drand48_data structure and making drand48_r() call erand48() , or you can go portable and use erand48() which is defined by POSIX and has been available since the 1980s on most Unix systems. erand48() function 采用一个数据结构(实际上,一个包含 3 个无符号短裤的数组)作为其 state。因此,您可以通过将其捆绑到本地定义的drand48_data结构并调用drand48_r()来为 Mac OS X 实现drand48_r() erand48() ,或者您可以 go 便携式并使用erand48() ,它由 POSIX 定义并且自 1980 年代以来在大多数 Unix 系统上可用。 Personally, I'd go for portability, but writing a simple drand48_r() is also straight-forward except for sorting out which header declares it.就个人而言,为了可移植性,我会使用 go,但是编写一个简单的drand48_r()也很简单,除了整理出 header 声明的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM