我的科研代码如下:
#define TRIALS 1000000
#define LEN 10
int i;
for(i=0;i<TRIALS;i++) {
uint8_t r[LEN];
getRand(r, LEN);
doExperiment(r);
}
我使用/ dev / urandom获取随机数:
void getRand(uint8_t *r, int len) {
int rand = open("/dev/urandom", O_RDONLY);
read(rand, r, len);
close(rand);
}
注意:我不要求我的实验是可重复的,所以不要关心固定的种子。但是,是任务关键,我的随机数是高质量的(合理地接近加密安全),因此我的结果的统计数据是有效的。速度也很重要。
我计划将此代码并行化,首先使用OpenMP,只需在我的循环前面加上#pragma omp parallel for
即可。
问题:同时生成随机数的最佳方法是什么(建议不要使用/ dev / urandom)?我应该在调用getRand()时使用互斥量并允许我的代码序列化获取随机数,我是否应该尝试预先生成我需要的所有随机数,或者我应该有一个单独的线程来填充随机缓冲区以生产者 - 消费者的方式从(使用互斥锁)读取的数字?如果我使用/ dev / random代替最好的解决方案,这是一个有限的资源并且可能会阻塞?
我已阅读有关并行生成随机数的相关文章,但希望特别针对使用/ dev / {urandom,random}提出问题。
答案 0 :(得分:0)
巩固一些评论......
对从/ dev / urandom读取的getRand()
函数进行多次调用很慢并且应该避免,因为它使用会增加大量开销的系统调用。最好从/ dev / urandom读取更大的块并缓冲它们,或者使用/ dev / urandom来播种软件PRNG。
在后一种情况下,可以使用OpenSSL的RAND_bytes()
返回“加密强随机”值。这可以配置为通过RDRAND指令使用英特尔的DRNG(参见http://wiki.openssl.org/index.php/Random_Numbers#Hardware),讨论here。这实际上是通过AES-NI指令集(也可以通过OpenSSL's EVP API直接访问)在计数器模式下使用AES的硬件实现。 According to Intel支持RDRAND的OpenSSL版本的性能比非RDRAND版本高出一个数量级。
用于为多个线程生成随机数的两种方法(在this post中讨论)要么为/ dev / urandom中的每个线程播种单独的PRNG,要么从/ dev / urandom中播种一个PRNG然后播种每个线程的PRNG来自那个。
但应该注意, OpenSSL不是线程安全的。 This post给出了一个使用OpenSSL和OpenMP的好例子。