# Why is there a huge performance gap using Map with more than 100 List entries

im using Map on a List like this:

cube= {{1, 1, 1}, {1, 1, 2}, {1, 1, 3}, {1, 1, 4}, ... , {5, 5, 4}, {5, 5, 5}}


Mapping the whole List with 125 entries takes like 2.5s.

AbsoluteTiming[
Map[Apply[d[[#1, #2, #3]] &, #] &, cube];
]

{2.552146, Null}


Mapping in two sublists with less than 100 entries the whole thing takes nearly no time.

 AbsoluteTiming[
Join[
Map[Apply[d[[#1, #2, #3]] &, #] &, cube[[1 ;; 99]]],
Map[Apply[d[[#1, #2, #3]] &, #] &, cube[[100 ;; 125]]]
];

]

{0., Null}


Why is there a huge performance gap? An how do I avoid it except splitting my list?

• Btw your cube is equal to Tuples[Range[5],3], just so you know :). Jul 16, 2014 at 10:56
• @TeakeNutma I bet ... here really means {2,9,12},{tweedledee,tweedledum, "tweedleDUN"}. This reminds me of a book by a mathematician I once read which pointed out a remarkable device that physicists have come up with, namely, $\ldots$, which allows them to solve practically any problem simply by omission.
– acl
Jul 16, 2014 at 11:04
• Can you show what d is? and isn't this the same : Map[d[[Sequence @@ #]] &, cube]? I cant reproduce this slowness even on much larger lists. Jul 16, 2014 at 15:13
• @george2079 I've added an example in my answer, take a look
– acl
Jul 16, 2014 at 20:55

If you look at SystemOptions[], like so,

Column[
OpenerView /@
(Replace[SystemOptions[], Rule[x_, y_] -> List[x, y],
1])
]


you see that under CompileOptions, if you click on the triangle to open it,

there is an option "MapCompileLength" -> 100. Set it to eg 10 and see it it helps (do SetSystemOptions["CompileOptions" -> {"MapCompileLength" -> 10}]).

This option determines the length of the list above which Mathematica (tries to) compile the function to be mapped.

EDIT: Example:

Here's some data:

Length[cube = Tuples[Range[10], 4]]


And here's a function which is a) inefficient on purpose, b) designed to be compilable as-is (that's why I localise s, so that Compile will work).

d = (Module[{s = 0}, Do[s = s + #[[i]]^2, {i, Length@#}];s] &)


Now, set the auto-compilation length for Map to 100 (the default):

SetSystemOptions["CompileOptions" -> {"MapCompileLength" -> 100}]


and now test:

Needs["GeneralUtilities"]
Quiet@BenchmarkPlot[d /@ # &, cube[[1 ;; #]] &, Range[90, 110]]
`

• Maybe I'm dense today. Your example got faster at length 100, which I understand, but the OP's got slower at length 100, which I do not understand. Am I missing something? Jul 16, 2014 at 23:32
• @MichaelE2 oops, no, I am dense! You're right. Well then the example is inapplicable. Maybe they should just set the length to infinity and see what happens.
– acl
Jul 16, 2014 at 23:34
• @acl maybe the compilation itself is fairly expensive, and not worth the 'payoff'? Jul 17, 2014 at 13:49
• @TaliesinBeynon that's the only explanation I could think of, too. Let's see when/if we are shown the function. It might involve lots of subexpressions so that time is spent on optimizing them, for example.
– acl
Jul 17, 2014 at 14:19