【问题标题】:Can't create huge arrays无法创建巨大的数组
【发布时间】:2015-09-02 22:08:28
【问题描述】:

像许多其他程序员一样,我加入了primes,和他们中的许多人一样,我喜欢挑战,所以我不希望像 Atkin 这样做的速度比你老兄这样的评论,但只是我的问题的一个解决方案——或者至少是一个提示。

我需要创建 big 数组(比如 size > int.MaxValue)。所以我去了很多网页,找到了gcAllowVeryLargeObjects Element一个。我以为我得救了,给我的App.config添加以下魔法:

<configuration>
  <runtime>
    <gcAllowVeryLargeObjects enabled="true" />
  </runtime>
</configuration>

但它没有工作。这是我使用的代码:

void go(object sender, EventArgs eventArgs)
{
    t.Stop();
    ulong maxprime = 10;
    Stopwatch stopwatch = new Stopwatch();
    string s = String.Empty;
    while (maxprime < ulong.MaxValue)
    {
        stopwatch.Restart();
        richTextBox2.Text += Environment.NewLine + ("Max \t= " + maxprime.ToString("N0"));
        try
        {
            richTextBox2.Text += Environment.NewLine + ("Count \t= " + GetAllPrimesLessThan(maxprime).Count);
            richTextBox2.Text += Environment.NewLine + ("Time \t= " + stopwatch.Elapsed);
            richTextBox2.Text += Environment.NewLine + ("--------------------------------");
            maxprime *= 10;
            richTextBox2.Refresh();
        }
        catch (Exception exception)
        {
            s = exception.Message + "; Allocation size: " + (maxprime + 1).ToString("N0");
            break;
        }
        
    }
    if (!string.IsNullOrEmpty(s))
    {
        richTextBox2.Text += Environment.NewLine + s;
    }
    richTextBox2.Text += Environment.NewLine + ("Done.");
}

private static List<ulong> GetAllPrimesLessThan(ulong maxPrime)
{
    var primes = new List<ulong>() { 2 };
    var maxSquareRoot = Math.Sqrt(maxPrime);
    var eliminated = new bool[maxPrime + 1];

    for (ulong i = 3; i <= maxPrime; i += 2)
    {
        if (!eliminated[i])
        {
            primes.Add(i);
            if (i < maxSquareRoot)
            {
                for (ulong j = i * i; j <= maxPrime; j += 2 * i)
                {
                    eliminated[j] = true;
                }
            }
        }
    }
    return primes;
}

哪个输出这个:

[...]
Max     = 1 000 000 000
Count   = 50847534
Time    = 00:00:15.3355367
--------------------------------
Max     = 10 000 000 000
Array dimensions exceeded supported range.; Allocation size: 10 000 000 001
Done.

我怎样才能摆脱这个错误?


仅供参考:我有

  • 16GB 内存;
  • 32GB 内存映射(/paged?)在 SSD 上;
  • 已启用 64 位

【问题讨论】:

  • 如果你想避免创建巨大的数组,你应该考虑分区。您可以在NIST FIPS spec 中找到一个微妙的参考。第 80 页(如果在 Chrome 中查看,则为 90 页)。你仍然不能超过2,147,483,647 元素,但你可以接近那么多素数。
  • 查看这个有类似的讨论和解释,它是指使用 BigArray 超过 2 GB 限制stackoverflow.com/questions/1087982/…
  • 老兄... 错误的公牛。我知道现在需要大型数组,但您应该使用分区或其他技术来避免内存不足。

标签: c# arrays


【解决方案1】:

来自您的链接:

在您的应用程序配置文件中使用此元素可启用大小超过 2 GB 的数组,但不会更改对象大小或数组大小的其他限制:

对于字节数组和单字节结构的数组,任何一维的最大索引为 2,147,483,591 (0x7FFFFFC7),其他类型的最大索引为 2,146,435,071 (0X7FEFFFFF)。

另见What is the maximum length of an array in .NET on 64-bit Windows

理论上,一个数组最多可以有 2,147,483,647 个元素,因为它使用 int 进行索引

【讨论】:

    【解决方案2】:

    如果您达到整数最大范围的界限,您可以选择使用基于long-index 的数组。

    问题是C# indexer properties 不支持此功能,它使用int。您可以使用 Array.CreateInstance(Type, long[]) 手动构建它们。

    请注意,您必须使用 Array.GetValue(long) 获取值。

    【讨论】:

    • Array.CreateInstance(typeof(int), Int32.MaxValue) 在 64 位上抛出 OutOfMemoryExceptionArray.CreateInstance(typeof(int), UInt32.MaxValue) 抛出 “不支持大于 2GB 的数组”,即使启用了 gcAllowVeryLargeObjects 设置... (.NET 4.5.3)。
    猜你喜欢
    • 2017-07-08
    • 2012-02-23
    • 1970-01-01
    • 2015-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 2018-12-13
    相关资源
    最近更新 更多