2015-06-17 2 views
7

Как и многие другие программисты, я вошел в primes, и, как и многие из них, мне нравится вызов, поэтому я не ищу комментариев, таких как Atkin сделал это быстрее, чем вы, чувак , а просто решение - или, по крайней мере, намек - на мою проблему.Невозможно создать огромные массивы

Мне нужно создать большие массивы (как размер>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. 

Как я могу избавиться от этой ошибки?


FYI: У меня

  • 16GB оперативной памяти;
  • Память 32 ГБ отображается (/ paged?) На SSD;
  • 64бит включен
+0

Если вы хотите избежать создания огромных массивов, вам следует рассмотреть раздел. Вы можете найти тонкую ссылку в спецификации [NIST FIPS] (http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf). Страница 80 (это 90, если просмотр в Chrome). Вы по-прежнему не можете превышать элементы «2 147 483 647», но вы можете приблизиться к множеству простых чисел. –

+0

Проверьте это, чтобы обсудить и объяснить это, это относится к использованию BigArray , чтобы выйти за пределы 2 ГБ. http://stackoverflow.com/questions/1087982/single-objects-still-limited-to-2-gb- in-size-in-clr-4-0 –

+2

Чувак ... Неверный бык. Я знаю, что теперь требуются большие массивы, но вы должны использовать разделение или другую технику, чтобы НЕ ВЫПОЛНИТЬ ПАМЯТЬ. – dr4cul4

ответ

13

Из Вашей ссылки:

Используя этот элемент в файле конфигурации приложения позволяет массивы, которые больше, чем 2 Гб, но не изменяет другие ограничения на объект размер или размер массива:

Максимальный индекс в любом одном измерении равен 2,147,483,591 (0x7FFFFFC7) для массивов байтов и массивов однобайтовых структур и 2,146,435,071 (0X7FEFFFFF) для других типов.

Смотрите также What is the maximum length of an array in .NET on 64-bit Windows:

Массив может теоретически иметь в большинстве 2147483647 элементов, , так как он использует Int для индексации.

+0

Быстро и чисто. Я должен научиться искать больше:/ –

4

Если вы попали в рамки целочисленного диапазона максимумов, вы можете выбрать массив long -index.

Проблема в том, что это не поддерживается C# indexer properties, в котором используется int. Вы можете создать их вручную, используя Array.CreateInstance(Type, long[]).

Обратите внимание, что вы должны получить значения, используя Array.GetValue(long).

+0

Это звучит хорошо! Я посмотрю asap –

+1

'Array.CreateInstance (typeof (int), Int32.MaxValue)' throws 'OutOfMemoryException' на 64 бит,' Array.CreateInstance (typeof (int), UInt32.MaxValue) 'throws _" Массивы более 2 ГБ не поддерживаются "_ даже с включенным параметром' gcAllowVeryLargeObjects' ... (.NET 4.5.3). – CodeCaster

Смежные вопросы