2016-12-11 7 views
0

У меня есть код:System.OutOfMemoryException при работе с большими списками

this.weights_StoA = new List<List<double>>(); 

if (NETWORK_MODE == 0) 
{ 
    Random rand = new Random(); 

    int count = enters.Count; 

    Parallel.For(0, HIDDEN_NEURONS_COUNT, (i, loopState) => 
    { 
     List<double> weights = new List<double>(); 

     for (int j = 0; j < count; j++) 
     { 
      weights.Add(rand.NextDouble()); 
     } 

     lock (weights_StoA) 
     { 
      weights_StoA.Add(weights); 
     } 
    }); 
} 

weights_StoA является List<List<double>>.

Я работаю с большими массивами. HIDDEN_NEURONS_COUNT = 63480, entres.Conut = 126960. Этот код генерирует System.OutOfMemoryException. Я попытался изменить архитектуру на x64, но она по-прежнему вызывает одно и то же исключение.

Как это исправить? Буду очень признателен, если вы поможете мне решить эту проблему!

+5

Sidenote: 'Random' не поточно- – Caramiriel

+7

Ваш алгоритм выделит' 63,480 * 126,960' (это '8,059,420,800' экземпляров) из' double' (8 байт) значения, это '64,475,366,400' байты или ** 60 гигабайт **. Неудивительно, что у вас заканчивается память. – Dai

+0

Вопрос в том, что вы делаете с этим списком. Вы должны работать не со списками, а с перечнем и шаблоном проектирования производителя/потребителя, чтобы сборщик мусора мог исключить использование данных. –

ответ

2

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

List<double> weights = new List<double>(count); 
for(int j = 0; j < count; j++) 
{ 
    weights.Add(rand.NextDouble()); 
} 

или:

double[] weights = new double[count]; 
for(int j = 0; j < count; j++) 
{ 
    weights[j] = rand.NextDouble(); 
} 
+0

Почему это одобренный ответ? как он решит проблему? это как «игнорировать реальную проблему, эта оптимизация ничего не изменит», ваш комментарий к вопросу должен быть помечен как ответ – barakcaf

+0

@barakcaf Мой комментарий «переосмыслить проблему» на самом деле не является ответом, потому что он не предлагает конкретного решение. По крайней мере для других людей с аналогичными проблемами есть вероятность, что избежать перераспределения списка решит это для них. – Dai

0

garbagge коллектор .Net не уплотняет больших объектов, чтобы избежать воздействия Performace. Таким образом, у вас есть 2 варианта:

  1. Выделите массив для больших данных.

  2. Периодически задает стоимость недвижимости GCSettings.LargeObjectHeapCompactionMode по GCLargeObjectHeapCompactionMode.CompactOnce. Следующий вызов GC будет иметь дело с большими объектами, и сбрасывается значение по умолчанию. См https://msdn.microsoft.com/en-us/library/system.runtime.gcsettings.largeobjectheapcompactionmode(v=vs.110).aspx