您的位置:首页 > 其它

如何创建一个可以保存13亿数据的数组?兼谈时间和空间之间永无休止的战争

2012-12-01 14:17 656 查看
Q:在为了测试一个简单算法的性能问题,想创建一个超大数组,结果遇到了错误,于是在知乎上问了这样一个问题:

我想用一个数组保存全国人民的年龄,用如下代码,

却得到

F:\code\demo.cpp(73) : error C2148: 数组的总大小不得超过 0x7fffffff 字节

如何申请超过这个限制的大数组?

A:

知乎上真是卧虎藏龙,很快,余天升老师给出了理论上的分析:

昨天看到这个问题的时候,手上正好没有编译器用。今天帮你确认了这个问题。

这个跟Windows的内存管理机制有关系。我们都知道,在进程中,所有使用的地址都是虚拟地址,进程也是运行在虚拟内存中的,虚拟内存的地址和物理内存中的地址通过页表进行转换。在32位Windows中,能够表示的最大寻址范围就是4G,每一个进程都独享4G的虚拟内存。而Windows采取是这样子分配的:将4G空间分成两部分,低2G的部分是给用户使用的,而高2G的部分是保留给系统使用的。这样子,每一个进程真正能够使用的内存就只有2G。而这个2G,包括了栈和堆,以及存放常量和静态数据的区域。

不过2G内存很早以前就已经不够用了,所以微软对于32位系统给出这样的调整方法,可以使用4-gigabyte tunine(4GT),将进程使用的部分扩大至3G,或者,通过BCDEdit /set进行更改,进行不限于3G的扩充。不过不管怎么样,4G的限制不能超越。这种算是作为老系统而且对内存需要一般大软件的折衷方案。

2G 内存大小限制是Windows(32位)的限制,是没有办法超越的。解决办法就是编译为64位程序。你试一下就知道了,把数据类型改成char(一个字节),然后申请的空间再大一点,但是不用到0x7fffffff那么大,尽管能够编译通过,但是运行时会申请内存失败,也就是说,不仅仅是数据不能申请那么大,总内存的使用也不能操作这个限制。如果编译为64位程序,你的代码不需要做任何更改就能编译通过了。

关于虚拟地址空间:http://msdn.microsoft.com/en-us/library/windows/desktop/aa366912

关于如何编译64位应用程序:http://msdn.microsoft.com/zh-cn/library/9yb4317s.aspx

周杰老师给出了具体的解决方案:

现代的Windows早已进入64位了,这是个简单的问题,我可以非常坚定的回答你,可以做到!

不过首先,你必须确保你的电脑的13亿*4字节……至少得要8G以上的内存(依你想要的数额而定,越大越好),64位的Windows,还有IDE,并确保IDE的目标构架是64位的CPU

在IDE中输入以下代码,然后编译运行:

刚刚测试了一下,发现这个使用Windows API是大材小用了,使用C或者C++自有的动态内存分配完全就可以解决问题:

很多人在评论中提到,创建这么大的数组,我是不是疯了?或者说是个白痴?

其实,我也是觉得这种情况在实际的开发中比较少见,至少我从来没有遇到过,这里,也只是为了极限测试而已。然而,祁育老师在评论中给了这样一个现实的例子:

这个地方这么用确实不好,但是现实中确实有这么用的,听过腾讯的负责QQ币系统的介绍过,他们存用户当前的Q币值的时候就是开一个几亿个元素的数组放到内存里,数组下标用就是用户的QQ号,元素值为当前Q币值,相当于是一个命中为100%的缓存

这个例子和这段评论,让我想到了程序中时间和空间之间那永无休止的战争。在空间比较紧张的时候,我们往往用富裕的时间去换取空间,而在空间比较富裕的时候,我们又会用富裕的空间去换取时间。这条规则,可以在这个例子中得到全面的体现。如果这是一台586的古董机器,我们不得不借助硬盘的虚拟内存来保存数据,硬盘读写当然远远比内存读写来的慢,这自然会让程序花费更多的时间。这就是用富裕的时间换空间。而如果这是一台拥有128G内存的超级服务器,那就省事了,全部数据都在内存中,程序比神舟九号上天还快。这就是用富裕的空间换取时间。

时间和空间的矛盾,似乎从来都没有调和过,这成了一场永无休止的战争。

而程序员在此时所扮演的角色,大约就是一个出色的政治家了。他巧妙地在时间和空间之间取得平衡。在时间富裕的时候,用时间换取空间。在空间富裕的时候,用空间换取时间。还是用QQ做例子,在那些顽固派看来,用那么大的数组保存数据,简直是对宝贵的内存资源的无耻浪费,应该拉出去枪毙,然而,这些空间却换来了100%的查找命中率,换来了更加宝贵的响应度。

对QQ来说,多加几根或者几十根内存条洒洒水啦,而响应度却是他的命根子。

大约,这就是程序员权衡的艺术。

其实,毛主席早已经告诉我们了

抓主要矛盾,抓主要矛盾的主要方面。

——毛泽东:《矛盾论》

看来,程序员们有空的时候,少打一会游戏,多读一读主席的著作,也很有必要啊。

转载自:有间客栈
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐