您的当前位置:首页正文

c库的randrandom随机数产生函数性能差?

2023-09-24 来源:步旅网
c库的randrandom随机数产⽣函数性能差?

有⽹⽂称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 2 #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; i125 arrCount[ rand % STAT_NUM ]++;126 }127

128 printf(\"Total count: %lu\\n\", count);129 for(size_t i=0; i130 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; i147 arrCount[ rand % STAT_NUM ]++;148 }149

150 printf(\"Total count: %lu\\n\", count);151 for(size_t i=0; i152 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 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; i169 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; i175 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; i191 arrCount[ rand % STAT_NUM ]++;192 }193

194 printf(\"Total count: %lu\\n\", count);195 for(size_t i=0; i196 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; i212 arrCount[ rand % STAT_NUM ]++;213 }214

215 printf(\"Total count: %lu\\n\", count);216 for(size_t i=0; i217 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; i233 arrCount[ r % STAT_NUM ]++;234 }235

236 printf(\"Total count: %lu\\n\", count);237 for(size_t i=0; i238 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; i254 size_t r = rand();

255 arrCount[ r % STAT_NUM ]++;256 }257

258 printf(\"Total count: %lu\\n\", count);259 for(size_t i=0; i260 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 }

因篇幅问题不能全部显示,请点此查看更多更全内容