【问题标题】:OutOfMemoryException on declaration of Large Array声明大数组时出现 OutOfMemoryException
【发布时间】:2011-01-27 11:00:53
【问题描述】:

我必须创建一个相当大的双数组 12000ish x 55000ish。不幸的是,我遇到了内存不足的异常。我以前用 Java 开发,可以更改内存设置。这对 C# 是可能的还是不可能的?我正在使用 VS 2008。

【问题讨论】:

  • 我建议你考虑一个“内存不足”的数据结构(即数据库)。为什么要存储这么大的双精度数组?
  • 我也对“相当”这个词的选择笑了。
  • 不用担心我会将内容保存在数据库中。
  • 也许在设置LARGE_ADDRESS_AWARE-PE-Flag时也能解决问题

标签: c#


【解决方案1】:

每个 double 是 8 个字节,因此您尝试分配一个刚刚超过 5GB 的数组。 CLR 的每个对象限制约为 2GB IIRC,即使对于 64 位 CLR 也是如此。换句话说,问题不在于可用的内存总量(尽管如果您没有足够的内存显然会遇到问题),而是每个对象的大小。

我建议您将其拆分为更小的数组,也许在某种描述的外观后面。我不相信有任何方法可以解决单个数组的限制。

编辑:您可以选择一个数组数组 - 也就是 锯齿状数组

double[][] array = new double[12000][];
for (int i = 0; i < array.Length; i++)
{
    array[i] = new double[55000];
}

你能接受吗?

(您不能使用矩形数组 (double[,]),因为这会产生相同的每个对象大小问题。)

【讨论】:

  • 不是单个双精度数组,我认为他的意思是二维数组
  • 虚拟内存不是问题。您正在尝试分配 5GB 的内存,但限制为 2GB。 :)
  • 另外,由于内存碎片,OP 在尝试分配数百 Mb 的连续块时可能会遇到问题。
  • @csetzkorn 如果数据非常稀疏,那么它们可能根本不应该在数组中。使用Dictionary&lt;int, double&gt; 来存储数据。只要大约一半的值是空的,它可能会使用更少的空间。
  • @Servy:鉴于接受度,我怀疑 OP 实际上很好,因为锯齿状数组使用了大量内存。现在 5GB 已经不是那么了 :)
【解决方案2】:

由于您无法创建大于 2GB 的对象,您可以尝试使用 MemoryMappedFile 来处理所需大小的内存块。

var data = MemoryMappedFile.CreateNew("big data", 12000L * 55000L); var view = data.CreateViewAccessor(); var rnd = new Random(); for (var i = 0L; i < 12000L; ++i) { for (var j = 0L; j < 55000L; ++j) { var input = rnd.NextDouble(); view.Write<double>(i * 55000L + j, ref input); } }

【讨论】:

    【解决方案3】:

    如果您的总内存足够,您可以通过创建一堆较小的数组并将它们包装在单个 IList&lt;T&gt; 或其他一些索引接口中来防止 LOH 碎片导致的内存不足异常。

    这是一个描述它的链接:

    BigArray&lt;T&gt;, getting around the 2GB array size limit

    致谢:this post (C# chunked array)

    【讨论】:

      【解决方案4】:

      嗯,要么你的内存不足(关闭一些程序),要么你达到了内存分配限制(大约 2Gb),这个内存需要是一个连续的块。您可以使用 64 位机器,在这种情况下您将拥有更多可用内存,或者我认为您可以让应用程序感知大地址(如果在这种情况下可能,谷歌搜索会告诉您如何执行此操作)。

      相信您在 Boot.ini 文件中添加了 /3GB 开关以实现大地址感知。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-02
        相关资源
        最近更新 更多