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 }
c库的rand/random随机数产生函数性能差?相关推荐
- python中rand函数是什么意思_科学网-Python中*和**作用及随机数产生函数 np.random.rand()/numpy.random.unifo...-张伟的博文...
[第一部分] Python中的 * 和 ** ,能够让函数支持任意数量的参数,它们在函数定义和调用中,有着不同的目的! 一. 打包参数 * 的作用:在函数定义中,收集所有位置参数到一个新的元组,并将整 ...
- 【C++】random随机数与【C++11】/rand()和srand()的用法
文章目录 随机数 1. c++ 11 random随机数的使用(推荐使用) 1.1 1.2 1.3 1.4 2.1 C++中随机函数rand()和srand()的用法(老本版) 2.2 限制随机数的范 ...
- C++随机数(rand和srand)函数用法详解
C++ 提供了一组函数以生成和使用随机数字.随机数字就是从一组可能的值中进行随机选择而获得的一个值.该组中的值都有相同的被选中的几率. 随机数字常用于许多不同类型的程序中,以下是一些示例: 计算机游戏 ...
- np.randon模块,numpy.random模块各函数功能详解,分类描述各个函数功能,生成随机数
因为网上很多文章都是在依次列举各个函数的功能,并没有做分类,所以记忆上还有使用上都不方便. 本文旨在将功能相似的函数放在一起,以及对它们进行辨析和区分,便于精准地调用.未完待续 最权威的参考来源:Ra ...
- php 随机数rand,PHP随机数函数rand()与mt_rand() - 米扑博客
PHP 中 rand()与mt_rand()都是用于产生一个指定范围内单独随机数的函数,如果需要产生多个不重复的随机数,请参考:PHP生成指定范围内的N个不重复的随机数. 既然他们都是用于产生一个随机 ...
- c语言rand函数时间种子,C语言中以时间为种子,产生随机数的函数
srand((unsigned)time(NULL) +++++++++++++++++++++++++++++++++++++++++++++++++ 以时间为种子,其实再产生随机数的函数中都会加, ...
- c语言怎么产生随机数函数,详细介绍一下C语言里面的随机数产生函数random怎么用...
匿名用户 1级 2013-11-24 回答 rand()函数可以用来产生随机数e799bee5baa6e79fa5e98193e4b893e5b19e31333332643334,但是这不是真真意义上 ...
- 计算机的随机数函数,使用rand()函数生成随机数
rand()函数生成随机数.计算机无法生成真正的随机数,它只产生所谓的伪随机数. 生成伪随机数,需要stdlib.h头文件. 参考以下代码: #include #include int main() ...
- C++ Primer 5th笔记(chap 17 标准库特殊设施)随机数
1. 场景: rand 生成随机数 此函数生成均匀分布的伪随机整数, 每个随机数的范围在 0 和一个系统相关的最大值( 至少为 32767) 之间. 1.1 问题: 一些应用需要随机浮点数. 一些程序 ...
最新文章
- 2022-2028年中国FEP薄膜行业市场发展规模及市场分析预测报告
- 并不对劲的bzoj2820:p2257:YY的GCD
- array,arraylist,string的总结
- 分布式系统原理 之6 两阶段提交协议
- c++中的继承--1(引出,继承方式,继承的对象模型)
- 发布一个jQuery插件:formStorage
- Redis中数据结构和编码详细图解(应用场景及优缺点)
- Linux下cacti+syslog-ng+snare
- 用Unity的GetSpectrumData方法识别钢琴曲中的钢琴琴键
- 看《当幸福来敲门》观后感
- 【应急基础】————13、VBS遍历目录获取文件Hash
- 点上并集符号的解释,并集符号上有一点,这是什么符号?文中解答
- 网络编程-procmon
- GEE(8):使用MODIS填补由去云后的Landsat影像计算得到的NDVI数据
- TP5.1实现支付宝线下收银(扫码枪扫描用户支付宝付款码支付)
- 做人与做事的对立与统一
- 脑洞全开YY无罪-益智类游戏“脑力大战”引发思考
- 2016百度之星 - 测试赛(热身,陈题)1001,1002,1003,1004
- 如何合并多个Excel文件(相同列结构)至一个Excel文件中
- 联想E530c 出现开机声音卡顿的问题
热门文章
- php与Ajax实例
- 在asp.net(C#)中怎么获得一个目录的大小?
- 【天线】天线基础:名词解释
- 【linux】shell中整数运算的加、减、乘、除
- 【Git】git系统学习(一):常用指令
- html判断国家,nginx通过geoip2模块实现判断用户来源国家跳转中英站
- cssbefore图片大小_两小时学会CSS-before after 伪元素
- latex 中文_【小白向】LaTeX 中文入门
- 傻瓜式动画制作软件_一个傻瓜版的动画制作软件——万彩动画大师
- linux查找项目中的问题,教你如何快速定位项目中慢查询[项目管理]