CLR 4.0仍然限制单个对象大小不超过2GB?

43

据我所知,在.NET中,单个实例的限制为2GB。由于我主要在32位操作系统上工作,因此并没有太关注这一点。在32位上,它更多地是人为的限制,不过我很惊讶地发现,这种限制也适用于64位.NET

由于像List<T>这样的集合使用数组来存储项目,这意味着在32位上运行的.NET应用程序能够比在64位上运行的同一应用程序在列表中存储两倍的引用类型项目。在我看来,这相当令人惊讶。

有人知道CLR 4.0是否解决了这个限制吗(我目前手头没有4.0安装)。


8
更新 2012 年:截至 .NET 4.5,在x64系统上,开发者现在可以分配比 2GB 更大(远远更大)的对象。 2GB 的限制已经被取消了。http://www.centerspace.net/blog/nmath/large-matrices-and-vectors/?preview=true&preview_id=221&preview_nonce=7d1678c20c - Paul
2
正确的链接似乎是http://www.centerspace.net/blog/nmath/large-matrices-and-vectors/。 - Brian Rasmussen
2
即使已经更正的链接也失效了 :( - RBT
尝试使用此链接获取有关绕过2GB限制(MSDN)的信息:https://msdn.microsoft.com/zh-cn/library/hh285054(v=vs.110).aspx - John Thoits
1
已更正链接:https://www.centerspace.net/large-matrices-and-vectors - Trevor Misfeldt
3个回答

55
这比想象中更糟——当您在32位的.NET中工作时,您的进程空间要小得多。在32位.NET应用程序中,我的经验是您始终会在内存使用量达到1.2-1.4GB左右时开始出现内存不足错误(有些人说他们可以达到1.6GB…但我从未见过)。当然,在64位系统上,这不是问题。
话虽如此,即使在64位系统上,单个2GB的引用类型数组也是巨大的对象数量。即使有8字节的引用,您也可以分配一个包含268,435,456个对象引用的数组,每个引用都可以非常大(高达2GB,如果它们使用嵌套对象,则可以更大)。 这比大多数应用程序所需的内存更多。 CLR 团队成员曾发表博客,介绍了一些解决这些限制的方法。在64位系统上,像他的BigArray<T>这样的方法将是将任意数量的对象分配到数组中的可行解决方案,远远超过2GB的单个对象限制。 P / Invoke也可以允许您分配更大的数组。

编辑:我也应该提到这一点——我认为在.NET 4中,这种行为并没有发生任何变化。自.NET开始以来,这种行为就没有改变过。


编辑:.NET 4.5现在将在x64中提供选项,通过在app.config中设置gcAllowVeryLargeObjects来明确允许对象大于2GB。


1
没问题 - 我只是加了这个因为在64位和32位中真的没有更糟糕的。理论上的限制是对象的1/2,但由于你真正受限于总共1.4gb的进程空间,所以没有办法创建一个接近允许大小一半的对象引用数组。(每个引用都需要指向某些东西,以及引用的大小...所以在.NET 32位中,你真正的上限大多数时候在1/4gb左右的引用)。 - Reed Copsey
1
Brian:这只是64位与32位之间一个(虽然在我看来很小的)劣势。有许多理由不要转向64位,但人们似乎忘记了这一点,认为64位自动更好。 - Reed Copsey
1
我已经阅读到Mono支持C#中的64位数组(例如,具有超过2^32个条目的数组)。 - waterlooalex
2
是的,Mono可以做到这一点。请注意,所有CLR实现都具有理论能力(所有数组都具有“long LongLength”属性),但迄今为止只有Mono实际使用了它。 - Pavel Minaev
我相信你在提到大小时每次提到的“gb”都代表千兆字节(GB)。内存寻址方案总是以字节为单位,但是关于大小的帖子让我感到困惑。如果有错漏,请您澄清或保持一致吗? - RBT
显示剩余5条评论

17

@Rick,你在哪里看到4GB的? - Marc Gravell
4
数组中元素的最大数量为UInt32.MaxValue。 - Rick Minerich
1
@Rick k; 那么一个包含uint.MaxValue个元素的int[]有多大? - Marc Gravell
@MarcGravell 数组大小是sizeof(type) * num_elements加上一些开销。在您的示例中,它将是4 * uint.MaxValue或17,179,869,180。 - Peter Oehlert
1
如果你需要一个 byte[],那么你的限制是4GB。 - binki
显示剩余2条评论

14

在数字领域中,这是一件大事。任何在.NET中使用数字类库的人都将它们的矩阵存储为数组。这样可以调用本地库来进行数值计算。2GB的限制严重制约了64位.NET中可能存在的矩阵大小。更多信息


1
我们已经和微软就这个问题进行过沟通。虽然在 .NET 4.0 中不太可能解决,但他们似乎非常愿意找到一个解决方案。我认为我们最终会使用长索引数组,但更有可能是某种巨型 blob 对象。 - Trevor Misfeldt
一个6553665536的浮点数数组的性能如何与65536个65536浮点数数组相比?256个256浮点数数组的性能将不如256256数组,因为后者具有更好的缓存局部性,而前者则没有,但如果访问矩阵的行足够本地化以从缓存局部性中受益,我认为处理器将能够缓存对象表引用。 - supercat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接