zoukankan      html  css  js  c++  java
  • c库的rand/random随机数产生函数性能差?

    有网文称c标准库的rand/random随机数产生函数性能极差。一直信以为真,但从没做过验证。最近因其他因缘,写了些代码专门验证rand/random的性能。结果大出意料,颠覆之前的成见。

    结论如下:

    1) rand/random性极佳。在64位机器上,其性能大约比简单自增略低30%(32位的自增比64位性能高出1倍以上)!

    2) srand/srandom性能极差极差。绝对不能每次调用rand之前都调用srand。这么做不仅没必要,还会极大降低性能,性能只有调用rand的1%!!!

    3) rand文档中提到的实现示例也实际实现存在差别,尤其是srand实现!

    4) rand的实现起始就是简单的乘法和取模,简单的随机数实现在性能上几乎无法超越系统自带的标准实现!

    5) 网上的东西很多真是不靠谱!!!

    下面测试代码,代码在64/32位机器都能运行。

    编译命令:g++ -o3 -o test random.cpp

      1 #include <stdio.h>
      2 #include <stdint.h>
      3 #include <vector>
      4 #include <algorithm>
      5 
      6 #include <stdlib.h>
      7 #include <math.h>
      8 
      9 #include <sys/time.h>
     10 
     11 
     12 #define NUM_RAND_SEED    100
     13 
     14 
     15 class Random
     16 {
     17     public:
     18         static int srandom(size_t randSeedNum = NUM_RAND_SEED);
     19 
     20         static size_t random();       
     21 
     22     private:
     23         static bool    m_bInit;
     24         static size_t  m_count;
     25         static std::vector<size_t> m_randSeeds;
     26 };
     27 
     28 bool    Random::m_bInit = false;
     29 size_t  Random::m_count = 0;
     30 std::vector<size_t>  Random::m_randSeeds;
     31    
     32 int Random::srandom( size_t randSeedNum )
     33 {
     34     m_randSeeds.clear();
     35     
     36     for(size_t i=0; i< randSeedNum; ++i){
     37         m_randSeeds.push_back( i );
     38     }
     39     
     40     std::random_shuffle(m_randSeeds.begin(), m_randSeeds.end());
     41     m_bInit = true;
     42 
     43     printf("Random::srandom\n");
     44     return 0;
     45 }
     46 
     47 size_t Random::random()
     48 {
     49     if( ! m_bInit ) {
     50         srandom();
     51     }
     52 
     53     static size_t size = m_randSeeds.size();
     54     return 16777619 * m_randSeeds[ m_count ++ % size ];
     55     
     56     //return 16777619 * m_randSeeds[ m_count ++ % NUM_RAND_SEED ];
     57     //return 16777619 * m_randSeeds[ (m_count ++) & 0xffL ];
     58 }
     59 
     60 // 简单随机数
     61 int MyRandom()
     62 {
     63     static struct timeval tv;
     64     static size_t iCount = 0;
     65     
     66     tv.tv_usec += 54321;
     67     if( tv.tv_usec > 1000000){
     68         tv.tv_usec -= 1000000;
     69     }
     70     if( iCount++ % 1000 == 0 ){
     71         gettimeofday(&tv, NULL);
     72     }
     73 
     74     return tv.tv_usec;
     75 }
     76 
     77 // 自增
     78 int Inc()
     79 {
     80     static size_t iCount = 0;
     81     
     82     return iCount++;
     83 }
     84 
     85 //////////////////////////////////////////////
     86 
     87 struct timeval stStartTv;
     88 
     89 //return past time. uint: us
     90 long PostTime(struct timeval *pstStartTv)
     91 {
     92     struct timeval  stEndTv;
     93     gettimeofday(&stEndTv, NULL);
     94     struct timeval* pstCurrTv = &stEndTv;
     95 
     96     long sec, usec = 0;
     97     sec = pstCurrTv->tv_sec - pstStartTv->tv_sec;
     98     if ((usec = pstCurrTv->tv_usec - pstStartTv->tv_usec) < 0) {
     99         sec--;
    100         usec += 1000000;
    101     }
    102     usec += sec*1000000;
    103 
    104     return usec;
    105 }
    106 
    107 void LogPastTime(struct timeval *pstStartTv, const char* sStep)
    108 {
    109     long usec = PostTime(pstStartTv);
    110 
    111     printf("%s: Past time: %ld ms\n", sStep, usec / 1000);
    112 }
    113 
    114 #define STAT_NUM 100
    115 
    116 // 自增函数
    117 void TestInc(size_t count)
    118 {
    119     gettimeofday(&stStartTv, NULL);
    120     size_t arrCount[STAT_NUM] = {0};
    121     printf("Test Inc...\n");
    122 
    123     for(size_t i=0; i<count; ++i){
    124         size_t rand = Inc();
    125         arrCount[ rand % STAT_NUM ]++;
    126     }
    127 
    128     printf("Total count: %lu\n", count);
    129     for(size_t i=0; i<STAT_NUM; ++i){
    130         printf("%lu: count=%lu, ratio=%f\n", i, arrCount[i], arrCount[i] * 1.0 / count);
    131     }
    132 
    133     LogPastTime(&stStartTv, "Inc");
    134     printf("Test Inc.\n");
    135 }
    136 
    137 // 简单自增
    138 void TestInc2(size_t count)
    139 {
    140     gettimeofday(&stStartTv, NULL);
    141     size_t arrCount[STAT_NUM] = {0};
    142     printf("Test Inc...\n");
    143 
    144     static size_t icount = 0;
    145     for(size_t i=0; i<count; ++i){
    146         size_t rand = icount ++;
    147         arrCount[ rand % STAT_NUM ]++;
    148     }
    149 
    150     printf("Total count: %lu\n", count);
    151     for(size_t i=0; i<STAT_NUM; ++i){
    152         printf("%lu: count=%lu, ratio=%f\n", i, arrCount[i], arrCount[i] * 1.0 / count);
    153     }
    154 
    155     LogPastTime(&stStartTv, "Inc");
    156     printf("Test Inc.\n");
    157 }
    158 
    159 // 
    160 void TestMyRandom(size_t count)
    161 {
    162     Random::srandom();  // not cala time
    163 
    164     gettimeofday(&stStartTv, NULL);
    165     size_t arrCount[STAT_NUM] = {0};
    166     printf("Test My Random...\n");
    167 
    168     for(size_t i=0; i<count; ++i){
    169         size_t rand = Random::random();
    170         arrCount[ rand % STAT_NUM ]++;
    171     }
    172 
    173     printf("Total count: %lu\n", count);
    174     for(size_t i=0; i<STAT_NUM; ++i){
    175         printf("%lu: count=%lu, ratio=%f\n", i, arrCount[i], arrCount[i] * 1.0 / count);
    176     }
    177 
    178     LogPastTime(&stStartTv, "MyRandom");
    179     printf("Test My Random.\n");
    180 }
    181 
    182 // 简单随机数
    183 void TestSimpleRandom(size_t count)
    184 {
    185     gettimeofday(&stStartTv, NULL);
    186     size_t arrCount[STAT_NUM] = {0};
    187     printf("Test Simple Random...\n");
    188 
    189     for(size_t i=0; i<count; ++i){
    190         size_t rand = MyRandom();
    191         arrCount[ rand % STAT_NUM ]++;
    192     }
    193 
    194     printf("Total count: %lu\n", count);
    195     for(size_t i=0; i<STAT_NUM; ++i){
    196         printf("%lu: count=%lu, ratio=%f\n", i, arrCount[i], arrCount[i] * 1.0 / count);
    197     }
    198 
    199     LogPastTime(&stStartTv, "Simple Random");
    200     printf("Test Simple Random.\n");
    201 }
    202 
    203 // random
    204 void TestRandom(size_t count)
    205 { 
    206     gettimeofday(&stStartTv, NULL);
    207     size_t arrCount[STAT_NUM] = {0};
    208     printf("Test Random...\n");
    209 
    210     for(size_t i=0; i<count; ++i){
    211         size_t rand = random();
    212         arrCount[ rand % STAT_NUM ]++;
    213     }
    214 
    215     printf("Total count: %lu\n", count);
    216     for(size_t i=0; i<STAT_NUM; ++i){
    217         printf("%lu: count=%lu, ratio=%f\n", i, arrCount[i], arrCount[i] * 1.0 / count);
    218     }
    219 
    220     LogPastTime(&stStartTv, "Sys Random");
    221     printf("Test Random.\n");
    222 }
    223 
    224 // rand
    225 void TestRand(size_t count)
    226 { 
    227     gettimeofday(&stStartTv, NULL);
    228     size_t arrCount[STAT_NUM] = {0};
    229     printf("Test Rand...\n");
    230 
    231     for(size_t i=0; i<count; ++i){
    232         size_t r = rand();
    233         arrCount[ r % STAT_NUM ]++;
    234     }
    235 
    236     printf("Total count: %lu\n", count);
    237     for(size_t i=0; i<STAT_NUM; ++i){
    238         printf("%lu: count=%lu, ratio=%f\n", i, arrCount[i], arrCount[i] * 1.0 / count);
    239     }
    240 
    241     LogPastTime(&stStartTv, "Sys Rand");
    242     printf("Test Rand.\n");
    243 }
    244 
    245 // 调用srand 和rand
    246 void TestRand2(size_t count)
    247 { 
    248     gettimeofday(&stStartTv, NULL);
    249     size_t arrCount[STAT_NUM] = {0};
    250     printf("Test Rand (and srand)...\n");
    251 
    252     for(size_t i=0; i<count; ++i){
    253         srand(i);
    254         size_t r = rand();
    255         arrCount[ r % STAT_NUM ]++;
    256     }
    257 
    258     printf("Total count: %lu\n", count);
    259     for(size_t i=0; i<STAT_NUM; ++i){
    260         printf("%lu: count=%lu, ratio=%f\n", i, arrCount[i], arrCount[i] * 1.0 / count);
    261     }
    262 
    263     LogPastTime(&stStartTv, "Sys Rand");
    264     printf("Test Rand.\n");
    265 }
    266 
    267 
    268 int main(int argc, char** argv)
    269 {
    270     size_t count = 10000;
    271     if( argc > 2){
    272         count = strtol(argv[2], NULL, 0);
    273     }
    274 
    275     if( argc < 2){
    276         printf("Usage: %s mode [count]\n", argv[0]);
    277         exit(0);
    278     }
    279 
    280     int mode = strtol(argv[1], NULL, 0);
    281     switch( mode )
    282     {
    283         case 0:
    284             TestInc(count);
    285             break;
    286 
    287         case 1:
    288             TestMyRandom(count);
    289             break;
    290     
    291         case 2:
    292             TestSimpleRandom(count);
    293             break;
    294      
    295         case 3:
    296             TestRandom(count);
    297             break;
    298  
    299         case 4:
    300             TestRand(count);
    301             break;
    302  
    303         case 5:
    304             TestRand2(count);
    305             break;
    306   
    307         case 6:
    308             TestInc2(count);
    309             break;
    310             
    311             
    312         default:
    313             printf("Unsupport mode: %d\n", mode);
    314     }
    315 
    316     return 0;
    317 }


    作者:zhenjing.chen
    出处:http://www.cnblogs.com/zhenjing/
    未注明转载的文章,版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    事件DOMContentLoaded与load的区别
    JavaScript的执行环境
    JS中函数运行的执行次序
    正则表达式30分钟入门教程
    mysql数据库备份
    杂篇
    memcached
    mysql问题解决
    php学习
    apache 安装
  • 原文地址:https://www.cnblogs.com/zhenjing/p/c_random.html
Copyright © 2011-2022 走看看