我有这样的科学研究代码:
#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/随机的方法,这是一个有限的资源,可能会阻塞,那么最好的解决方案会有所不同吗?
我已经阅读了关于并行生成随机数的相关文章,但我希望专门讨论一个关于使用/dev/{urandom,随机}的问题。
发布于 2014-05-11 15:15:19
为了巩固一些评论..。
对一个从/dev/urandom读取的getRand()函数进行多次调用是缓慢的,应该避免,因为它使用了增加大量开销的系统调用。最好从/dev/urandom中读取更大的块并对它们进行缓冲,或者使用/dev/urandom为软件PRNG注入种子。
在后一种情况下,可以使用OpenSSL的RAND_bytes()返回“加密强随机”值。这可以配置为使用英特尔的DRNG通过RDRAND指令(参见Numbers#Hardware),这是讨论的这里。这实际上是通过AES-NI指令集(也可以通过OpenSSL的EVP API直接访问)在计数器模式下使用AES的硬件实现。据英特尔 --支持RDRAND的OpenSSL版本比非RDRAND版本的性能高出一个数量级.
用于为多个线程生成随机数的两种方法(在这个职位中讨论)要么为/dev/urandom中的每个线程设置一个独立的PRNG,要么从/dev/urandom为一个PRNG种子,然后从该线程中为每个线程的PRNG注入种子。
但是应该注意的是,OpenSSL并不是线程安全的。这个职位给出了一个将OpenSSL与OpenMP结合使用的良好示例。
https://stackoverflow.com/questions/23591801
复制相似问题