Can not understand this timing result
For your first question
a=1.
tmptmp = Tuples[Range /@ {1000, 100}].{{3 a, 0}, {0, Sqrt[3] a}}
The basic answer is that in your first case
Transpose[# +
Transpose[{{0, 0}, {a, 0}, {-a/2, Sqrt[3] a/2}, {3 a/2,
Sqrt[3] a/2}}]] & /@ tmptmp
the variable a
gets evaluated many many times.
I simplified the problem by defining a small number of tuples.
tmptmp = Tuples[Range /@ {2, 1}].{{3 a, 0}, {0, Sqrt[3] a}}
Then ran a Trace
on
Trace[
Transpose[# +
Transpose[{{0, 0}, {a, 0}, {-a/2, Sqrt[3] a/2}, {3 a/2,
Sqrt[3] a/2}}]
] & /@ tmptmp
]
Below is an image of a formatted output from Trace
If you look closely you will see a
being evaluated over and over ... again.
Your second approach is much faster because it skips all those a
evaluations.
base = {{0, 0}, {a, 0}, {-a/2, Sqrt[3] a/2}, {3 a/2, Sqrt[3] a/2}};
Transpose[# + Transpose[base]] & /@ tmptmp //AbsoluteTiming
When you encounter problems like this With
can be used so that you don't have to define a global variable (i.e., one that sticks around).
The following form is just as fast as the one with base
defined globally.
With[
{
base = {{0, 0}, {a, 0},
{-a/2, Sqrt[3] a/2},
{3 a/2, Sqrt[3] a/2}}
},
Transpose[# + Transpose[base]] & /@ tmptmp
]
I am unaware of the answer to your second question about autocompile.
I address the second question.
Every now and then, questions turn up in connection with the autocompilation property of the function Map
, this one being the latest. In the comments, it was mentioned by @Karsten7 that the CompileOptions
can be set such that messages are generated if something goes wrong. That in fact answers more ore less the above question on how we can test if a function autocompiles one of its arguments.
Let us first inspect the CompileOptions.
SystemOptions["CompileOptions"]
(*
{CompileOptions->{ApplyCompileLength->\[Infinity],ArrayCompileLength->250,AutoCompileAllowCoercion->False,AutoCompileProtectValues->False,AutomaticCompile->False,BinaryTensorArithmetic->False,CompileAllowCoercion->True,CompileConfirmInitializedVariables->True,CompiledFunctionArgumentCoercionTolerance->2.10721,CompiledFunctionMaxFailures->3,CompileDynamicScoping->False,CompileEvaluateConstants->True,CompileOptimizeRegisters->False,CompileParallelizationThreshold->10,CompileReportCoercion->False,CompileReportExternal->False,CompileReportFailure->False,CompileValuesLast->True,FoldCompileLength->100,InternalCompileMessages->False,ListableFunctionCompileLength->250,MapCompileLength->100,NestCompileLength->100,NumericalAllowExternal->False,ProductCompileLength->250,ReuseTensorRegisters->True,SumCompileLength->250,SystemCompileOptimizations->All,TableCompileLength->250}}
*)
We see three options that could produce messages: CompileReportExternal
, CompileReportFailure
, InternalCompileMessages
. The last one generates a message when the compilation fails, and the second one takes care that it is reported. When we set them to True
, we will see a message when the compilation fails. Therefore, our test to see if a function autocompiles will simply be to use an argument for which the compilation fails. When we see the message, it autocompiles and otherwise not.
We also see some options that end on CompileLength
and have the name of a Mathematica function in front: Array
, Fold
, Map
, Nest
, Product
, Sum
, Table
. These are functions that do autocompile when the relevant argument is at least as long as the value given in the option.
Here is a demonstration. It is simple to construct a function that cannot be compiled. Just use a symbol without a value in the function body.
SetSystemOptions["CompileOptions" -> {"CompileReportFailure"->True, "InternalCompileMessages"->True}];
Clear[zz];
Array[#+zz&, {250}];
Fold[#+zz&, 0, Range[100]];
Map[#+zz&, Range[100]];
Nest[#+zz&, 0, 100];
Product[x+zz, {x, 1, 250}];
Sum[x+zz, {x, 1, 250}, Method->"Procedural"];
Table[x+zz, {x, 1, 250}];
(* During evaluation of In[4]:= Compile::compfail: Compilation of Array[#1+zz&,{250}] failed because zz was not a form suitable for the compiler.*)
(* other results skipped *)
All commands show a compilation error, similar to the one above. The function Sum
can be used with a lot of options. For many of them, there is nothing numerical to do, so then there is no autocompilation.
Of course, many more functions autocompile. For example:
NIntegrate[x+zz,{x,0,1}]
(* During evaluation of In[26]:= Compile::compfail: Compilation of x+zz failed because zz was not a form suitable for the compiler, etc *)
NSum[x+zz, {x, 1, 1}]
(* During evaluation of In[28]:= Compile::compfail: Compilation of x+zz failed because zz was not a form suitable for the compiler, etc *)
Plot[x+zz,{x,0,1}]
(* During evaluation of In[20]:= Compile::compfail: Compilation of x+zz failed because zz was not a form suitable for the compiler, etc *)
A little bit surprising: Table
does autocompile, but Do
does not:
Do[x+zz, {x, 1, 5000}]
(* no message *)