5

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?

Chris
  • 53
  • 2
  • Btw your cube is equal to Tuples[Range[5],3], just so you know :). – Teake Nutma Jul 16 '14 at 10:56
  • 1
    @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 '14 at 11:04
  • 1
    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. – george2079 Jul 16 '14 at 15:13
  • @george2079 I've added an example in my answer, take a look – acl Jul 16 '14 at 20:55

1 Answers1

9

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

acl
  • 19,834
  • 3
  • 66
  • 91
  • 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? – Michael E2 Jul 16 '14 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 '14 at 23:34
  • 1
    @acl maybe the compilation itself is fairly expensive, and not worth the 'payoff'? – Taliesin Beynon Jul 17 '14 at 13:49
  • 1
    @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 '14 at 14:19