5
$\begingroup$

Here is some simple code:

ClearSystemCache[];
d = 10^4;
mem1 = MemoryInUse[];
Sum[Sqrt[1 + j^2] // N[#, d] &, {j, 1, d}];
mem2 = MemoryInUse[];
(mem2 - mem1)/d // N

which outputs

3764.59

I wonder why Mathematica takes so much memory for this calculation. Trying to nudge it in the desired direction, I replaced the line Sum[Sqrt[1 + j^2] // N[#, d] &, {j, 1, d}]; by

s = 0; Do[s = s + Sqrt[1 + j^2] // N[#, d] &, {j, 1, d}] 

but got an even bigger output,

3971.35

As I see it, to compute the sum using the Do[] command, one only needs to keep in memory at most d digits of the current value of s, a few digits for the values of d=10^4 and j=1, ..., d, and however many digits needed to compute the current value of

Sqrt[1 + j^2] // N[#, d] &, which seems to be no more than just 1.2d digits on an average (somewhat surprisingly to me); indeed,

ClearSystemCache[];
d = 10^4;
mem1 = MemoryInUse[];
Sqrt[1 + 1^2] // N[#, d] &;
Sqrt[1 + d^2] // N[#, d] &;
mem2 = MemoryInUse[];
(mem2 - mem1)/d // N

outputs

2.3144

half of which is less than 1.2.

So, it seems that the total memory needed for this calculation should be, at most, about d+1.2d=2.2d digits, whereas Mathematica seems to say it takes almost 4000d bytes of memory.

Where is my mistake? More importantly, is it possible to get the desired behavior from Mathematica (preferably without losing the speed), and if so, how? Thank you for your help.

$\endgroup$
4
  • 2
    $\begingroup$ Although MMA might sort of look in some ways like an ordinary programming language. Under the surface it is very very different from what you might imagine, even after you know a great deal about it. If you need a language that runs your program in a few thousand bytes there are some available. You could try learning how to use the Compile function in MMA, but that may take more learning and even memory than what you have now. $\endgroup$
    – Bill
    Commented Mar 3, 2017 at 3:09
  • 1
    $\begingroup$ @Bill : I think Compile can only output machine-precision numbers, whereas I need a lot more precision. On the other hand, as mentioned in the question, Mathematica reports that it takes only about 1.2d bytes to compute d=10^4 digits of the square root. So, that part of the calculation probably cannot be a problem. So, the only problem seems to be that for some reason Mathematica keeps in memory all the updates of the value of s (and apparently something else as well?). But why would it do that, whatever kind of programming language it is? $\endgroup$ Commented Mar 3, 2017 at 3:36
  • $\begingroup$ @Mr.Wizard Actually you are right, the exact arithmetic version is indeed 56 after sharing... sorry for making that wrong remark saying they are the same $\endgroup$
    – vapor
    Commented Mar 3, 2017 at 3:56
  • $\begingroup$ "one only needs to keep in memory at most d digits of the current value of s" What you see is caching. The system anticipates that the same values may be re-used in the future and remembers some of the partial results. As Bill said, there is a lot more going on behind the scenes than what you might naively expect, and you should not read too much into measurements like this. $\endgroup$
    – Szabolcs
    Commented Mar 3, 2017 at 8:38

1 Answer 1

8
$\begingroup$

Mathematica caches all sorts of expressions that come up on the course of evaluation. Some but not all of these are cleared by ClearSystemCache.

By your use of the expression Sqrt[1 + j^2] // N[#, d] & you are performing exact symbolic computations and only then converting these to numeric equivalents. Mathematica will cache values in this process.

Put another ClearSystemCache[]; in your code before you check mem2 and you will see a very different number:

ClearSystemCache[];
d = 10^4;
mem1 = MemoryInUse[];
Sum[Sqrt[1 + j^2] // N[#, d] &, {j, 1, d}];
ClearSystemCache[];
mem2 = MemoryInUse[];
(mem2 - mem1)/d // N
9.9984

More suitable however is to avoid exact symbolic calculation in the first place.

Here I replace 1 with an arbitrary precision one with d digits of Precision:

$HistoryLength = 0;
d = 10^4
one = SetPrecision[1, d];
mem1 = MemoryInUse[]
out = Sum[Sqrt[one + j^2], {j, 1, d}];
mem2 = MemoryInUse[]
(mem2 - mem1)/d // N
10000

26294360

26298432

0.4072

This is sufficient to compute your result:

Precision[out]
10007.

In the code above simply allowing the result of d = 10^4 to print by omitting ; uses some memory, resulting in the final delta being smaller. (Since mem1 = MemoryInUse[] comes after this.) I suspect that this is because certain mechanisms are not fully primed until an expression is printed.

I also added $HistoryLength = 0.

$\endgroup$
7
  • $\begingroup$ I found something strange, if you replace the sum with Sum[Sqrt[i], {i, 10^4}];, the resulting memory in use is small (about 56), but with Sum[Sqrt[i] // N[#, d] &, {i, 10^4}];, the result is around 4363. In terms of output, the first one is bigger. From this result, it implies Mathematica did not store the first output. $\endgroup$
    – vapor
    Commented Mar 3, 2017 at 3:44
  • $\begingroup$ @happyfish I presume that the memory sharing (e.g. Share) is more efficient on that expression? $\endgroup$
    – Mr.Wizard
    Commented Mar 3, 2017 at 3:49
  • $\begingroup$ @Mr.Wizard : Thank you very much for your answer. The only problem here that is left for me at this point is why Mathematica reported a very small memory use (2.3144d/2<1.2d) per square root when doing it just for two numbers (as indicated in the question) -- but not when doing it for 10^4 numbers. Could you please help me with this as well? $\endgroup$ Commented Mar 3, 2017 at 4:32
  • $\begingroup$ @IosifPinelis I do not know the details of the caching scheme and I cannot at this time answer that question. It is possible that an increase in memory usage due to caching is hidden by a recovery of memory elsewhere in the system. Or it may be that caching is for whatever reason not triggered in this case. $\endgroup$
    – Mr.Wizard
    Commented Mar 3, 2017 at 4:48
  • $\begingroup$ @Mr.Wizard : Thank you very much again. Your answer was very illuminating to me. $\endgroup$ Commented Mar 3, 2017 at 13:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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