有⽹⽂称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 6 #include 9 #include 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 28 bool Random::m_bInit = false; 29 size_t Random::m_count = 0; 30 std::vector 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 128 printf(\"Total count: %lu\\n\", count);129 for(size_t i=0; i 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 150 printf(\"Total count: %lu\\n\", count);151 for(size_t i=0; i 155 LogPastTime(&stStartTv, \"Inc\");156 printf(\"Test Inc.\\n\");157 }158 159 // 160 void TestMyRandom(size_t count)161 { 162 Random::srandom(); // not cala time163 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 173 printf(\"Total count: %lu\\n\", count);174 for(size_t i=0; i 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 194 printf(\"Total count: %lu\\n\", count);195 for(size_t i=0; i 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 215 printf(\"Total count: %lu\\n\", count);216 for(size_t i=0; i 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 236 printf(\"Total count: %lu\\n\", count);237 for(size_t i=0; i 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 255 arrCount[ r % STAT_NUM ]++;256 }257 258 printf(\"Total count: %lu\\n\", count);259 for(size_t i=0; i 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 } 因篇幅问题不能全部显示,请点此查看更多更全内容