Сокращение использования памяти в расширенной сессии Mathematica
Я занимаюсь довольно длинными вычислениями, которые могут легко охватывать несколько дней. В ходе этих вычислений иногда у Mathematica заканчивается память. Для этого я пришел к чему-то вроде:
ParallelEvaluate[$KernelID]; (* Force the kernels to launch *)
kernels = Kernels[];
Do[
If[Mod[iteration, n] == 0,
CloseKernels[kernels];
LaunchKernels[kernels];
ClearSystemCache[]];
(* Complicated stuff here *)
Export[...], (* If a computation ends early I don't want to lose past results *)
{iteration, min, max}]
Это здорово и все, но со временем основное ядро накапливает память. В настоящее время мое основное ядро питается примерно 1,4 ГБ оперативной памяти. Есть ли способ заставить Mathematica очистить память, которую он использует? Я пробовал littering Share
и Clear
в течение многих Modules
, которые я использую в своем коде, но память все еще, кажется, накапливается с течением времени.
Я также попытался удостовериться, что у меня нет ничего большого и сложного, выполняющегося за пределами Module
, так что что-то не остается слишком длинным. Но даже при этом у меня все еще есть проблемы с памятью.
Есть ли что-нибудь, что я могу сделать по этому поводу? У меня всегда будет большой объем памяти, так как большинство моих вычислений связаны с несколькими большими и плотными матрицами (обычно 1200 x 1200, но это может быть больше), поэтому я с осторожностью отношусь к использованию MemoryConstrained
.
Update:
Проблема была именно в том, что сказал Алексей Попков в своем ответе. Если вы используете Module
, память со временем будет течь медленно. В этом случае это усугублялось, потому что у меня было несколько операторов Module[..]
. "Основной" Module
находился в пределах ParallelTable
, где сразу выполнялось 8 ядер. Отметьте (относительно) большое количество итераций, и это стало питательной средой для лотов утечек памяти из-за ошибки с Module
.
Ответы
Ответ 1
Поскольку вы широко используете Module
, я думаю, вам может быть интересно узнать эту ошибку с не удалением временных переменных Module
.
Пример (не удаляя несвязанные временные переменные с их определениями):
In[1]:= $HistoryLength=0;
a[b_]:=Module[{c,d},d:=9;d/;b===1];
[email protected][$Context<>"*"]
Out[3]= 6
In[4]:= lst=Table[a[1],{1000}];
[email protected][$Context<>"*"]
Out[5]= 1007
In[6]:= lst=.
[email protected][$Context<>"*"]
Out[7]= 1007
In[8]:= [email protected]$999
Out[8]= Attributes[d$999]={Temporary}
d$999:=9
Обратите внимание, что в приведенном выше коде я установил $HistoryLength = 0;
, чтобы подчеркнуть это ошибочное поведение Module
. Если вы этого не сделаете, временные переменные все еще могут быть связаны из переменных истории (In
и Out
) и не будут удалены с их определениями по этой причине в более широком наборе случаев (это не ошибка, но особенность, как упомянул Леонид).
ОБНОВЛЕНИЕ: Только для записи. Существует еще одна старая ошибка с не удалением неизменяемых переменных Module
после Part
назначений им в v.5.2, которая не полностью фиксирована даже в версии 7.0.1:
In[1]:= $HistoryLength=0;$Version
Module[{L=Array[0&,10^7]},L[[#]]++&/@Range[100];];
Names["L$*"]
[email protected]@#&/@Names["L$*"]
Out[1]= 7.0 for Microsoft Windows (32-bit) (February 18, 2009)
Out[3]= {L$111}
Out[4]= {40000084}
Ответ 2
Вы пытались оценить $HistoryLength=0;
во всех подъядрах, а также в главном ядре? Отслеживание истории является наиболее распространенным источником для выхода из памяти.
Вы пытались не использовать медленный и потребляющий память Export
и вместо этого использовать быстрый и эффективный Put
?
Не понятно из вашего сообщения, где вы оцениваете ClearSystemCache[]
- в главном ядре или в подъядрах? Похоже, вы оцениваете его только в главном ядре. Попытайтесь оценить его во всех субядрах перед каждой итерацией.