Why does this nested sum appear to sleep between iterations?

5

1

I have a weird performance problem in a nested sum, which I've reduced to the following test case:

testTab = Table[1.`20, {i, 188}, {j, 301}, {k, 20}];
test[] := Sum[testTab[[1, 1, 1]] Sum[testTab[[1, 1, 1]], {n, 1, 250}], {m, 1, 10}]
Monitor[test[], {n, m}]

Here the output from Monitor is {n, 1} for a second, then it changes to {n, 2}, and so on until I get the result of 2500.0000000000000000. Obviously, table accesses shouldn't be that slow.

Even more interestingly, if I change the summation limit of the inner sum from 250 to 249 or smaller, I don't get this slowdown, the result appears almost instantly. I can even make table dimensions way larger, but this 250→249 transition still results in drastic performance difference.

What's happening here? Is it a bug?

I'm using Mathematica "11.1.0 for Linux x86 (32-bit) (March 13, 2017)", but this problem also happens on "9.0 for Linux x86 (32-bit) (November 20, 2012)" and on "11.0.1 for Linux ARM (32-bit) (January 17, 2017)" (Raspberry Pi 3).

Ruslan

Posted 2017-12-01T06:34:18.937

Reputation: 6 677

Same behavior in M8 – Bill Watts – 2017-12-01T07:46:09.883

Answers

8

The reason is that Mathematica tries to compile the code for sufficiently long Tables, Sums, and Products. The outer sum has 10 summands. That's too few. But starting the inner sum with 250 or more summands implies a compilation. 250 is the default value of the suboption "SumCompileLength" of the system option "CompileOptions":

"SumCompileLength" /. ("CompileOptions" /. SystemOptions[])

250

This compilation is done for each iteration of the outer Sum and induces some overhead. This is why it is a good idea to merge multiple sums into a single instance of Sum like this:

test2[] := 
 Sum[testTab[[1, 1, 1]] testTab[[1, 1, 1]], {n, 1, 250}, {m, 1, 10}]

Moreover, trying to use matrix-vector producs or Total may be even more efficient. Needless to say that nothing will beat testTab[[1, 1, 1]] 250 10 in this case.

Henrik Schumacher

Posted 2017-12-01T06:34:18.937

Reputation: 85 430

Well of course nothing will beat it, I've already mentioned that it's a reduced test case. Anyway, is there any means of making SumCompileLength way higher to avoid hitting this?

– Ruslan – 2017-12-01T08:00:21.347

1Yes, for example SetSystemOptions[ "CompileOptions" -> {"SumCompileLength" -> \[Infinity]}]. Use at your own risk. – Henrik Schumacher – 2017-12-01T08:16:29.130