c库的rand/random随机数产生函数性能差?
2012-06-10 19:17 zhenjing 阅读(9818) 评论(6) 编辑 收藏 举报有网文称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/
未注明转载的文章,版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。