对于c中的一些数值模拟,我需要生成许多具有指数分布的随机数(都具有相同的预定分布).目前,我的程序运行良好,但超过50%的cpu时间用于生成这些随机数.
我想要做的是以不阻塞模拟主循环的方式生成这些随机数.更确切地说,我想有一个线程,其工作是始终保持随机数“提前准备好”,并在有人读取这个随机数时立即生成一个新的.
有人知道这样做的好方法吗?
目前,我的顺序代码如下所示:
#include <stdio.h> #include <iostream> #include <random> using namespace std; // exponential random variable with parameter lambda class EXPGenerator{ exponential_distribution<> expo; mt19937 engine; //mersene twister public: EXPGenerator(double lambda){ expo = exponential_distribution<>(lambda); engine = mt19937(time(NULL)); } double step(){ return expo(engine); } }; int main(int argc,char *argv[]) { EXPGenerator expgen(2.0); for(int i=0; i<100000; i++) { double randv(expgen.step()); std::cout << randv << endl; // do something complicated } return 0; }
我使用clang -O2 –std = c 11 –stdlib = libc test.cpp -o test编译它
[编辑:上面加了-O2]
解决方法
使用有界队列并让一个线程将随机数推入此队列,并在队列满时让该线程阻塞队列.要获取随机数,请从队列中取出一个数字,并在队列为空时让消费者线程阻塞队列.
当队列中有空间和可用的cpu时间时,这种简单的设计将让生产者产生随机数.
优化:使用包含随机数列表的队列.在这种情况下,生产者将生成一个包含随机数的完整列表.消费者将使用列表中的列表保留缓存(可能在EXPGenerator内部).一旦缓存为空,缓存将填充队列中的新列表.这将减少上下文切换开销,并且应当(原因)仅应用,在测量显示时,这是有意义的.
队列应该基本上是一些std :: deque,其中T是随机数,或std :: vector(随机数列表).使用互斥锁同步对该std:队列的访问,并使用两个条件变量.一,表示有空间再次插入更多随机数.并且要发信号通知,队列中已经存在至少一个元素.让消费者等待第二个条件,当队列为空时让生产者等待第一个条件,当队列满了.