C++ 偏微分数值计算库_ESYSim仿真器介绍之一 C++库介绍

本文详细介绍了在ESYSim仿真器中如何使用C++标准库和C++11的随机数生成器来实现伪随机数。重点讨论了C++11中的各种随机数引擎和分布,以及Boost库的补充。ESYSim的randgen模块提供了一套方便的API来生成均匀分布和高斯分布的随机数,并进行了性能和概率分布的测试。测试结果显示,不同算法在方差和执行速度上存在差异,但最大偏差未能达到理想水平,可能影响仿真精度。
摘要由CSDN通过智能技术生成

fcfe7a6c60be6b741247718985f8ec91.png

本文档介绍在ESYSim仿真器中使用到的C++标准库或第三方库。

伪随机数产生器

伪随机数产生器是仿真器中非常常用的组件,比如片上网络中的负载产生器、片上网络中的随机仲裁器等。评价伪随机数的指标通常是重复周期,重复周期越长越好。同时,伪随机数的概率分布也很重要的。对于仿真器来说,伪随机数产生器需要在两个方面优化:

  • 在完整仿真过程中,伪随机数序列都不发生重复。
  • 当伪随机数足够多之后,伪随机数的概率分布趋近于期望的概率分布。
  • 伪随机数的序列是确定的,即给定相同的种子,伪随机数序列可以复现。

C语言的stdlib.h 中提供了rand函数用来产生[0, RAND_MAX)范围内的整形伪随机数。这是C语言ANSI标准中提供了唯一伪随机数产生函数。

为了弥补C/C++语言在伪随机数方面的缺陷,Boost库提供了比较丰富的伪随机数生成函数库boost/random。在C++11标准中,这个库从Boost库引入STL库中,头文件为#include <random>

与C语言不同,C++11的随机数生成器包含随机数产生器和随机数分布两个部分。根据随机数的生成方法,随机数产生器包括利用硬件随机数产生器构建的随机数设备random_device,利用算法生成伪随机数的生成器(线性同余、梅森纠缠以及借位减法),以及通过调整伪随机数序列的伪随机数生成器(消除块和洗牌排序)。每一种生成器都可以通过设置种子来复现伪随机序列。

  • 线性同余引擎(LCG)linear_congruential_engine。预设产生器minstd_rand0minstd_rand
  • 梅森纠缠引擎(Mersenne Twister)mersenne_twister_engine。预设产生器 mt19937 mt19937_64
  • 借位减法引擎(Subtract with carray) subtract_with_carry_engine。预设产生器ranlux24_baseranlux48_base
  • 消除块引擎(Discard)discard_block_engine 。预测产生器ranlux24ranlux48
  • 洗牌排序引擎(Shuffle)shuffle_order_engine。 预测产生器knuth_b

C++11提供的随机数分布包括均匀分布、伯努利分布(二项分布)、泊松分布、正态(高斯)分布以及采样分布。如果需要使用随机数分布,首先利用随机数产生器得到一个均匀分布的随机数;然后再通过随机数分布映射到需要的概率分布。

  • 均匀分布:uniform_int_distribution(整数均匀分布)和 uniform_real_distribution(浮点均匀分布)。
  • 伯努利分布:bernoulli_distributionbinomial_distributionnegative_binomial_distributiongeometric_distribution
  • 泊松分布:poisson_distributionexponential_distributiongamma_distributionweibull_distributionextreme_value_distribution
  • 正态分布:normal_distributionlognormal_distributionchi_squared_distributioncauchy_distributionfisher_f_distributionstudent_t_distribution
  • 采样分布:discrete_distributionpiecewise_constant_distributionpiecewise_linear_distribution

ESYSim中的randgen模块

ESYSim中的randgen模块用来为仿真过程产生随机数。这个模块的C++源文件和SWIG文件在路径srcs/rangen中;python封装和测试文件在路径python/randgen

使用randgen模块,需要创建EsyRandGen对象。创建EsyRandGen对象需要制定随机数的种子和随机数的生成算法。

EsyRandGen(long a = 1, RandGenAlg alg = C11_DEFAULT);

随机数的生成算法用枚举变量RandGenAlg表示。EsyRandGen选择对应的C++11随机数生成器产生随机数。 RandGenAlg定义如下。

    enum RandGenAlg
    {
        C11_DEVICE = 1,
        C11_MINSTD_RAND0 = 2,
        C11_MINSTD_RAND = 3,
        C11_MT19937 = 4,
        C11_MT19937_64 = 5,
        C11_RANLUX24_BASE = 6,
        C11_RANLUX48_BASE = 7,
        C11_RANLUX24 = 8,
        C11_RANLUX48 = 9,
        C11_KNUTH_B = 10
    };

如果创建EsyRandGen对象时提供的alg不属于上面的枚举类型,则EsyRandGen采用C语言标准定义的rand函数产生随机数。

EsyRandGen对象提供两类分布:均匀分布和高斯(正态)分布。由于C++是强类型语言,EsyRandGen提供了不同的函数用来产生不同数据范围的随机数。

  • 生成均匀分布的函数如下:
double flatDouble(double low, double high);
long flatLong(long low, long high);
unsigned long flatUnsignedLong(unsigned long low, unsigned long high);
unsigned long long flatUnsignedLongLong(unsigned long long low, unsigned long long high);

每一个函数产生在[low, high)之间的一个随机数。

  • 生成高斯分布的函数如下:
double gaussDouble(double mean, double variance);
long gaussLong(long mean, double variance);
unsigned long gaussUnsignedLong(unsigned long mean, double variance);
unsigned long long gaussUnsignedLongLong(unsigned long long mean, double variance);

函数产生的高斯分布满足均值为mean而且方差为variance

randgen模块的测试

randgen模块的测试程序在路径python/randgen/test.py。 由于使用的是C和C++11官方提供的随机数生成器,所以我们默认了伪随机序列的重复性能够满足要求,不进行测试。我们着重测试的是生成的随机序列的概率分布。测试程序采用最为基本的均匀分布的概率分布作为测试项目。

测试程序会测试由不同随机数生成算法得到的均匀分布的方差和执行速度。测试程序使用flatUnsignedLong产生规定范围内的整形随机数。统计产生的随机数,可以得到每一个数值出现的频次,对频次求方差作为均匀分布的方差。

均匀分布的范围由min_rangemax_range确定;每一种随机数产生算法需要对seed_count种随机数种子进程测试;每一个随机数产生算法和随机数种子的测试需要产生number个随机数。

根据网络负载产生的场景,我们假设:均匀分布的范围是[0, 99);总共测试50个随机数种子;并且每组测试的随机数为100000个随机数。经过多次测试,C语言标准函数rand以及Minstd_rand0Ministd_randMt19937Mt19937_64四种算法的方差接近,一般都是小于0.001。具体数值随随机数种子波动。另外5种方法的方差较大,一般都大于0.001。

执行时间上,C语言标准函数rand的执行时间最小;Minstd_rand0Ministd_randMt19937Mt19937_64四种算法的执行时间大于rand。另外5种方法的执行时间较大。

此外,我们发现不同算法的最大偏差(某个数值出现的频次相对于理想均匀分布的频次的偏差)相对稳定(大于10%),并且无法下降。用于片上网络仿真器,这是一个较大的缺陷。如果用这样的随机数产生通信负载,某个目标地址可能比其他地址少10%的通信流量;或者多10%的通信流程。本人才疏学浅,暂时没有找到能够获得最大偏差更小的随机数算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值