有网文称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随机数产生函数性能差?相关推荐

  1. python中rand函数是什么意思_科学网-Python中*和**作用及随机数产生函数 np.random.rand()/numpy.random.unifo...-张伟的博文...

    [第一部分] Python中的 * 和 ** ,能够让函数支持任意数量的参数,它们在函数定义和调用中,有着不同的目的! 一. 打包参数 * 的作用:在函数定义中,收集所有位置参数到一个新的元组,并将整 ...

  2. 【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 限制随机数的范 ...

  3. C++随机数(rand和srand)函数用法详解

    C++ 提供了一组函数以生成和使用随机数字.随机数字就是从一组可能的值中进行随机选择而获得的一个值.该组中的值都有相同的被选中的几率. 随机数字常用于许多不同类型的程序中,以下是一些示例: 计算机游戏 ...

  4. np.randon模块,numpy.random模块各函数功能详解,分类描述各个函数功能,生成随机数

    因为网上很多文章都是在依次列举各个函数的功能,并没有做分类,所以记忆上还有使用上都不方便. 本文旨在将功能相似的函数放在一起,以及对它们进行辨析和区分,便于精准地调用.未完待续 最权威的参考来源:Ra ...

  5. php 随机数rand,PHP随机数函数rand()与mt_rand() - 米扑博客

    PHP 中 rand()与mt_rand()都是用于产生一个指定范围内单独随机数的函数,如果需要产生多个不重复的随机数,请参考:PHP生成指定范围内的N个不重复的随机数. 既然他们都是用于产生一个随机 ...

  6. c语言rand函数时间种子,C语言中以时间为种子,产生随机数的函数

    srand((unsigned)time(NULL) +++++++++++++++++++++++++++++++++++++++++++++++++ 以时间为种子,其实再产生随机数的函数中都会加, ...

  7. c语言怎么产生随机数函数,详细介绍一下C语言里面的随机数产生函数random怎么用...

    匿名用户 1级 2013-11-24 回答 rand()函数可以用来产生随机数e799bee5baa6e79fa5e98193e4b893e5b19e31333332643334,但是这不是真真意义上 ...

  8. 计算机的随机数函数,使用rand()函数生成随机数

    rand()函数生成随机数.计算机无法生成真正的随机数,它只产生所谓的伪随机数. 生成伪随机数,需要stdlib.h头文件. 参考以下代码: #include #include int main() ...

  9. C++ Primer 5th笔记(chap 17 标准库特殊设施)随机数

    1. 场景: rand 生成随机数 此函数生成均匀分布的伪随机整数, 每个随机数的范围在 0 和一个系统相关的最大值( 至少为 32767) 之间. 1.1 问题: 一些应用需要随机浮点数. 一些程序 ...

最新文章

  1. 2022-2028年中国FEP薄膜行业市场发展规模及市场分析预测报告
  2. 并不对劲的bzoj2820:p2257:YY的GCD
  3. array,arraylist,string的总结
  4. 分布式系统原理 之6 两阶段提交协议
  5. c++中的继承--1(引出,继承方式,继承的对象模型)
  6. 发布一个jQuery插件:formStorage
  7. Redis中数据结构和编码详细图解(应用场景及优缺点)
  8. Linux下cacti+syslog-ng+snare
  9. 用Unity的GetSpectrumData方法识别钢琴曲中的钢琴琴键
  10. 看《当幸福来敲门》观后感
  11. 【应急基础】————13、VBS遍历目录获取文件Hash
  12. 点上并集符号的解释,并集符号上有一点,这是什么符号?文中解答
  13. 网络编程-procmon
  14. GEE(8):使用MODIS填补由去云后的Landsat影像计算得到的NDVI数据
  15. TP5.1实现支付宝线下收银(扫码枪扫描用户支付宝付款码支付)
  16. 做人与做事的对立与统一
  17. 脑洞全开YY无罪-益智类游戏“脑力大战”引发思考
  18. 2016百度之星 - 测试赛(热身,陈题)1001,1002,1003,1004
  19. 如何合并多个Excel文件(相同列结构)至一个Excel文件中
  20. 联想E530c 出现开机声音卡顿的问题

热门文章

  1. php与Ajax实例
  2. 在asp.net(C#)中怎么获得一个目录的大小?
  3. 【天线】天线基础:名词解释
  4. 【linux】shell中整数运算的加、减、乘、除
  5. 【Git】git系统学习(一):常用指令
  6. html判断国家,nginx通过geoip2模块实现判断用户来源国家跳转中英站
  7. cssbefore图片大小_两小时学会CSS-before after 伪元素
  8. latex 中文_【小白向】LaTeX 中文入门
  9. 傻瓜式动画制作软件_一个傻瓜版的动画制作软件——万彩动画大师
  10. linux查找项目中的问题,教你如何快速定位项目中慢查询[项目管理]