本文共 3477 字,大约阅读时间需要 11 分钟。
有网文称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 #include2 #include 3 #include 4 #include 5 6 #include 7 #include 8 9 #include 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 m_randSeeds; 26 }; 27 28 bool Random::m_bInit = false; 29 size_t Random::m_count = 0; 30 std::vector 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 100115 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 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 }