Skip to main content

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?



Answer



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,


enter image description here


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]]

enter image description here


Comments