Skip to main content

memory - How to force Mathematica to clean up the cache



(see the bottom of this question for the MWE)


I'm working with a set of numerical data: numerous (a few thousands) files in the style of list of vectors (quadruplets x, y, vx, vy). Files are named as v1.txt, v2.txt, ..., vk.txt, where k is a few thousands. I am using For loop in Mathematica, in each cycle several steps are performed:


1) load vi.txt
2) make list of pairs of pairs from it (in the form of {{x1, y1},{v1x, v1y}, ...})
3) construct absolute value of the vector field ({{x1, y1}, norm of {v1x, v1y}, ...})
4) Make list density plot of the absolute value list
5) Make list stream plot of the pairs of pairs
6) export both.

The problem is that after about 200 cycles, Mathematica sucks up all the physical memory available in my machine and the kernel crashes. I tried using:



1) $HistoryLength = 0
2) ClearSystemCache[] after every cycle
3) ClearAll[(plots, data)] after every cycle
4) all of the above combined

up to no avail. What am I doing wrong? What should I do to tell Mathematica to get rid of the images from the previous step, so it won't suck up all of my RAM? The code I'm using is as follows:


$HistoryLength = 0;
SetDirectory[NotebookDirectory[]];
Monitor[
For[i = 1, i <= 5383, i++,

v = Partition[
Partition[
Flatten@Import["output\\results\\v" <> ToString[i] <> ".txt",
"Table"], 2], 2];
Absv = Table[{v[[i, 1, 1]], v[[i, 1, 2]], Norm[v[[i, 2]]]}, {i, 1,
Length@v}];
LDP = ListDensityPlot[Absv, PlotRange -> Full,
ColorFunction -> ColorData[{"SolarColors", "Reverse"}],
MaxPlotPoints -> 100, ImageSize -> 1000];
LSP = ListStreamPlot[v, StreamStyle -> White, StreamPoints -> Fine,

StreamScale -> 0.1, ImageSize -> 1000];
Export["output\\results\\img" <> ToString[i] <> ".png", LDP];
Export["output\\results\\img_stream" <> ToString[i] <> ".png", Show[LDP, LSP]];
ClearSystemCache[];
ClearAll[v,Absv,LDP,LSP];
], i]

Why is Mathematica completely ignoring all statements $HistoryLength, ClearSystemCache and ClearAll?


MWE


This is a minimal working example demonstrating my problem (not depending on any mysterious data that I have on my HDD):



MemoryInUse[]
Do[
ListStreamPlot@
Table[{{Random[], Random[]}, {Random[], Random[]}}, 1000];
ClearSystemCache[],
{i, 10}
];
MemoryInUse[]

Together with Henrik we figured out ListStreamPlot is the culprit, therefore I reported this as a bug.




Answer



This is also not an answer (I think you found the culprit and it needs to be solved by WRI) but a suggestion for a workaround. The idea is to run the memory leaking code in an extra kernel and restart that kernel every once in a while. Using the parallel functionality of current Mathematica releases this is pretty simple and by choosing an appropriate value for the number of parallel kernels you could even take advantage of parallelism if desired.


Here is a simple example based on your minimal working example which demonstrates the idea and shows that the master kernel will not accumulate any memory:


LaunchKernels[1];
Print[MemoryInUse[]];
calcsPerKernel = 3;
Do[
With[{fname = "plot-" <> ToString[i] <> ".png"},
ParallelEvaluate[
Export[

FileNameJoin[{$HomeDirectory, "Desktop", fname}],
ListStreamPlot[
Table[{{Random[], Random[]}, {Random[], Random[]}}, 1000]
]
];
Print[MemoryInUse[]];
]
];
If[Mod[i, calcsPerKernel] == 0,
CloseKernels[];

ClearSystemCache[];
LaunchKernels[1];
];
,
{i, 10}
];
CloseKernels[];
ClearSystemCache[];
Print[MemoryInUse[]];


The idea for a more general and flexible approach is as follows:



  • use LaunchKernels to launch the desired number of parallel kernels

  • use ParallelSubmit to pass the computations (e.g. per file) to the parallel kernel(s)

  • use WaitNext to get the result of a computation from the other kernel(s).

  • use CloseKernels[kernelid] and LaunchKernels to restart a/the parallel kernels


As it is very difficult to completely avoid memory leaks in sufficient complex Mathematica code I think this is a technique that will be helpful in many situations. We are using this approach regularly for computations that run for several days and have found that it works very reliable. Unlike some other parts of Mathematica the parallel toolkit seems to work very stable and reliable even on a larger scale.


Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...

Is there a way to do conditional matrix loop using 'continue'

I have the following: n = 3; m = 5; ww = RandomReal[{0, 0.1}, {n, n}]; uu = RandomReal[{0, 1}, {m, n}]; pp = RandomReal[{0, 1}, {n, n}]; ss = RandomInteger[{0, 5}, {m, n}]; Grid[{{"ww", "uu", "pp", "ss"}, {ww // TableForm, uu // TableForm, pp // TableForm, ss // TableForm}}, Spacings -> {5, 2}, Dividers -> All] where I would like to look at every element of matrix ss and produce a matrix tt , with zeroes at the locations in ss which have zeroes, and in all other positions do the following: tt = (-1/Subscript[ww, m]) Log[(1 - uu)/(Subscript[pp, m - 1])], where Subscript[ww, m] is the value at index of ww matrix and where Subscript[pp, m - 1] is the value at index-1 of pp matrix. So for example if the first value ever read from matrix ss happens to be 2, then value taken from matrix ww would be from the row 2, but from pp would be from row 1. Also how to tell difference between a 0 as a valid value from within the matrix elemen...