0
$\begingroup$

I wonder why NIntegrate uses memory. I have a long integral computation repeated thousands times. The memory use then goes up and speed goes down. I think I spot a problem with the way NIntegrate does not clear the memory of its variables.

Here is a simple example:

NI[z_?NumericQ, b0_?NumericQ] := 
 NIntegrate[E^-Abs[y - z], {y, -b0, b0}]

m1 = MemoryInUse[];

For[i = 1, i < 10000, i++; NI[RandomReal[], .5]] // AbsoluteTiming

m2 = MemoryInUse[];

m2 - m1
{117.606048, Null}

40405872

So, it does not clear 40 Mb... How to make NIntegrate clear the memory after it execute?

$\endgroup$
0

1 Answer 1

4
$\begingroup$

Update 3

As ilian correctly states in the comments, without NIntegrate we get the same picture as shown in the "Update 2" section. It proves that memory grow reflects temporary memory allocation by Table, and ClearSystemCache[] does completely eliminate the memory leak.

We can also switch off the caching completely:

SetSystemOptions[
 "CacheOptions" -> {"Numeric" -> {"Cache" -> False}, "Symbolic" -> {"Cache" -> False}}];

(*preloading of necessary packages*)
NIntegrate[E^-Abs[y], {y, -1, 1}]; RandomReal[];

(*startup memory usage when all the packages are already loaded*)
start = MemoryInUse[];

lst2 = Table[NIntegrate[E^-Abs[y - RandomReal[]], {y, -.5, .5}];
   MemoryInUse[] - start, {10000}];

final = MemoryInUse[] - start;

ListLinePlot[lst2, GridLines -> {None, {final}}]

plot

Update 2

With ClearSystemCache[] I obtain the following:

(*preloading of necessary packages*)
NIntegrate[E^-Abs[y], {y, -1, 1}]; RandomReal[];

(*startup memory usage when all the packages are already loaded*)
start = MemoryInUse[];

lst2 = Table[NIntegrate[E^-Abs[y - RandomReal[]], {y, -.5, .5}]; ClearSystemCache[];
   MemoryInUse[] - start, {10000}];

final = MemoryInUse[] - start;

ListLinePlot[lst2, GridLines -> {None, {final}}]

plot

Fit[lst2, {1, x}, x]
72075.5 + 16.0001 x

So ClearSystemCache[] solves the problem.

Update

After more careful checking I must agree that there is indeed a memory leak somewhere inside NIntegrate. I recommend to report it to the technical support. Consider the following (evaluate in a fresh kernel session):

(* preloading of necessary packages *)
NIntegrate[E^-Abs[y], {y, -1, 1}]; RandomReal[]; 

(* startup memory usage when all the packages are already loaded *)
start = MemoryInUse[];

lst2 = Table[NIntegrate[E^-Abs[y - RandomReal[]], {y, -.5, .5}]; 
   MemoryInUse[] - start, {10000}];

final = MemoryInUse[] - start;

ListLinePlot[lst2, GridLines -> {None, {final}}]

screenshot

(Mathematica 10.2 on Win7 x64).


Original answer

When you run NIntegrate for the first time it loads some .MX files containing implementation of the algorithms required for solving the requested problem. For example in version 10.2 on 64-bit Windows in fresh kernel when I evaluate NIntegrate[E^-Abs[y], {y, -1, 1}] the following packages are being loaded:

.\SystemFiles\Kernel\SystemResources\Windows-x86-64\NIntegrate\Strategies.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\NIntegrate\BNFDefinitions.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\NIntegrate\Exclusions.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\NIntegrate\LevinRule.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\NIntegrate\OscNInt.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\NIntegrate\DoubleExponentialOscillatory.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\NIntegrate\CommonRules.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\NIntegrate\MultiPeriodic.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\SpecialSimplifiers\Piecewise.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\GroebnerBasis.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\InverseFunctions.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\Regions\RegionUtils.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\NIntegrate\OscillatoryRescale.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\SpecialFunctions\SphericalBessel.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\SpecialFunctions\Hankel.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\SpecialFunctions\Struve.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\SpecialFunctions\SinIntegral.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\SpecialFunctions\HypergeometricPFQ.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\Holonomic\DifferentialRootReduce.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\Holonomic\HolonomicLibrary.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\ComplexExpand.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\SpecialSimplifiers\Simplify.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\SpecialFunctions\Fibonacci.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\Discrete\FourierFunctions.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\SpecialFunctions\Kelvin.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\SpecialFunctions\Nielsen.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\SpecialFunctions\HarmonicNumbers.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\NIntegrate\KronrodRules.mx
.\SystemFiles\Kernel\SystemResources\Windows-x86-64\NIntegrate\GeneralRule.mx

Using FileByteCount it is not difficult to find that these files have total size 996530 bytes. This is the main reason for larger memory usage after calling NIntegrate:

m1 = MemoryInUse[]
NIntegrate[E^-Abs[y], {y, -1, 1}];
MemoryInUse[] - m1
26437416

23227232

So it is not a memory leak, it is just the loaded packages take up some memory. If you really wish to unload them (what was not supposed by the developers, so I do not recommend to do this if it is not strictly needed), you can find some recipes in this thread.

$\endgroup$
7
  • $\begingroup$ What happens if you ClearSystemCache[]? It seems to go from a modest rate of increase to a negligible one. $\endgroup$
    – Michael E2
    Aug 18, 2015 at 14:25
  • $\begingroup$ @MichaelE2 I updated the answer. $\endgroup$ Aug 18, 2015 at 19:11
  • $\begingroup$ @AlexeyPopkov Does the plot still look increasing if you replace NIntegrate[]; with foo; or nothing? I think it just reflects temporary allocation needed by Table to build lst2 but that memory is not lost -- if you try evaluating the same piece of code multiple times and check the actual value of MemoryInUse[] after each time, does it always grow or does it stabilize? Of course, remember to set $HistoryLength=0 before this experiment. $\endgroup$
    – ilian
    Aug 19, 2015 at 22:38
  • 1
    $\begingroup$ @Alexey Not infinitely, I believe, since the cache size is bounded (and can be controlled via SystemOptions["CacheOptions"]). $\endgroup$
    – ilian
    Aug 20, 2015 at 2:40
  • 1
    $\begingroup$ @Alexey NIntegrate uses mostly "Numeric"; the max bytes refer to the size of a single entry in the cache table but by default there can be up to 7147 of them. Of course, setting "Cache" -> False will put a stop to it. $\endgroup$
    – ilian
    Aug 20, 2015 at 5:16

Not the answer you're looking for? Browse other questions tagged or ask your own question.