3
$\begingroup$

On V 9.01 on windows 7, all 64 bit.

I am sure I am missing something simple here, but I used all the tricks of the trade that I know about, and read docs, and do not see anything that helps.

Here is a compiled function made to speed up some computation.

When this function is put inside Plot or Table it resort back to being slow at the speed of the original uncompiled function speed.

Using Evaluate gives an error.

Here is a MWE (This function takes about one minute to evaluate and compile, sorry that is what I am using, but it is only one line, and takes one minute to compile)

ClearAll[f, g, g0, x, b, a];
f = Function[{##} /. {x_, b_, a_} :>Piecewise[{{Exp[-b*(-Log[x])^a], 0. < x <= 1.}}]];
g = InverseFunction[f, 1, 3];
g0 = Compile[{{x, _Real}, {a, _Integer}, {b, _Integer}}, g[x, a, b]]

Mathematica graphics

Timing[g0[.1, 3, 2]]
(* {0.156001, 0.416409} *)

and

Timing[g0[#, 3, 2] & /@ Range[0, 1, .1]]

Mathematica graphics

It is fast now. Uncompiled version takes more than 60 seconds for each one computation.

But when in a table, it becomes slow again, using the original version? or for some other reason

Table[Timing[g0[x, 3, 2]], {x, 0, .1, .1}]
(* {{61.308393, 0.00258519}, {61.323993, 0.416409}} *)

Evaluate gives error and still slow

Table[Evaluate[g0[x, 3, 2]], {x, 0, .1, .1}]
(*CompiledFunction::cfsa: "Argument x at position 1 should be a 
"machine-size real number " *)

Direct use of Table is too slow, same as above.

Table[g0[x, 3, 2], {x, 0, .1, .1}]

Same issue with Plot. Can't use Evaluate and if I do not, it is slow. Using Compiled-False did not help (since g0 is already compiled), it is still slow

Plot[g0[x, 3, 2], {x, 0, 1}, Method -> {Compiled -> False}]; (*slow*)
Plot[g0[x, 3, 2], {x, 0, 1}, Method -> {Compiled -> False}, Evaluated -> False]; 
Plot[g0[x, 3, 2], {x, 0, 1}, Evaluated -> False]; (*slow*)

How can one use Compiled function in Table and Plot without it being slow?

Is it one of those HoldRest, HoldFirst issues or I am missing something more basic here?

$\endgroup$
2
  • $\begingroup$ It doesn't get compiled in version 8.0.4, CompilePrint[g0] has MainEvaluate[ Hold[g][ R0, I0, I1]] and First@Timing[g0[#, 3, 2] & /@ Range[0, 1, .1]] gives 0.16, same as when using g directly. EDIT: Ran it again, now the timing was very slow... $\endgroup$
    – ssch
    Aug 1, 2013 at 10:54
  • $\begingroup$ As a workaround you could define the inverse as: g1[v_?NumericQ, b_Integer, a_Integer] := Block[{x}, x /. FindRoot[f[x, b, a] == v, {x, .5}]] which takes ~2s to plot, if you plan to use it often you could also interpolate it. $\endgroup$
    – ssch
    Aug 1, 2013 at 11:09

1 Answer 1

7
$\begingroup$

I think that in this instance, Compile is a red-herring. There is, however, something very strange going on.

Let's define your functions but do not use compilation. Start a shiny new kernel and do

ClearAll[f, g, g0, x, b, a];
f = Function[{##} /. {x_, b_, a_} :> 
     Piecewise[{{Exp[-b*(-Log[x])^a], 0. < x <= 1.}}]];
g = InverseFunction[f, 1, 3];

This function, g, is nice and fast as it is:

In[7]:= AbsoluteTiming[g[#, 3, 2] & /@ Range[0, 1, .1]]

Out[7]= {0.166521, {0.00258519, 0.416409, 0.480731, 0.53073, 0.575419,
   0.618365, 0.661898, 0.708357, 0.761299, 0.829109, 1.}}

Let's try the same thing in a Table.

In[8]:= AbsoluteTiming[Table[g[x, 3, 2], {x, 0, 1, 0.1}]]

Out[8]= {615.637676, {0.00258519, 0.416409, 0.480731, 0.53073, 
  0.575419, 0.618365, 0.661898, 0.708357, 0.761299, 0.829109, 1.}}

Yikes! 3697 times slower! Best go back to using a Map then:

In[9]:= AbsoluteTiming[g[#, 3, 2] & /@ Range[0, 1, .1]]

Out[9]= {56.093623, {0.00258519, 0.416409, 0.480731, 0.53073, 
  0.575419, 0.618365, 0.661898, 0.708357, 0.761299, 0.829109, 1.}}

Last time I evaluated this exact expression, it took 0.166 seconds. Now, it takes 56.1 seconds. It looks like Table broke the g function!

If you re-evaluate the definition of g:

ClearAll[f, g, g0, x, b, a];
f = Function[{##} /. {x_, b_, a_} :> 
     Piecewise[{{Exp[-b*(-Log[x])^a], 0. < x <= 1.}}]];
g = InverseFunction[f, 1, 3];

you get fast Mapping of g again:

In[17]:= AbsoluteTiming[g[#, 3, 2] & /@ Range[0, 1, .1]]

Out[17]= {0.166521, {0.00258519, 0.416409, 0.480731, 0.53073, 0.575419,
   0.618365, 0.661898, 0.708357, 0.761299, 0.829109, 1.}}

OK, so trying to make a Table of g seems to break g. It get's worse though. Restart the kernel and run the following

In[1]:= ClearAll[f, g, g0, x, b, a];
f = Function[{##} /. {x_, b_, a_} :> 
     Piecewise[{{Exp[-b*(-Log[x])^a], 0. < x <= 1.}}]];
g = InverseFunction[f, 1, 3];

In[4]:= AbsoluteTiming[g[#, 3, 2] & /@ Range[0, 1, .1]]

Out[4]= {0.158020, {0.00258519, 0.416409, 0.480731, 0.53073, 0.575419,
   0.618365, 0.661898, 0.708357, 0.761299, 0.829109, 1.}}

In[5]:= Table[x, {x, 1, 2, 1}]

Out[5]= {1, 2}

In[6]:= AbsoluteTiming[g[#, 3, 2] & /@ Range[0, 1, .1]]

Out[6]= {56.014613, {0.00258519, 0.416409, 0.480731, 0.53073, 
  0.575419, 0.618365, 0.661898, 0.708357, 0.761299, 0.829109, 1.}}

Simply executing Table in between two calls to a Map over g, slows down the Map by a factor of 350 or so!

EDIT:

For this issue, slowness in Table appears to be related to choice of variable. If you avoid the variables used in the definition of f, life is better. Again, from a clean kernel:

In[1]:= ClearAll[f, g, g0, x, b, a];
f = Function[{##} /. {x_, b_, a_} :> 
     Piecewise[{{Exp[-b*(-Log[x])^a], 0. < x <= 1.}}]];
g = InverseFunction[f, 1, 3];
Table[g[z, 3, 2], {z, 0, 1, 0.1}] // AbsoluteTiming

Out[4]= {0.161521, {0.00258519, 0.416409, 0.480731, 0.53073, 0.575419,
   0.618365, 0.661898, 0.708357, 0.761299, 0.829109, 1.}}

Plotting over z is also OK.

Plot[g[z, 3, 2], {z, 0, 1}] 

The above takes a couple of seconds on my machine.

EDIT 2

Redefining your function so that it uses unnamed slots appears to be the long term fix here.

In[6]:= f = 
  Function[Piecewise[{{Exp[-#2*(-Log[#1])^#3], 0. < #1 <= 1.}}]];
g = InverseFunction[f, 1, 3];

In[13]:= AbsoluteTiming[g[#, 3, 2] & /@ Range[0, 1, .1]]

Out[13]= {0.115015, {0.00258519, 0.416409, 0.480731, 0.53073, 
  0.575419, 0.618365, 0.661898, 0.708357, 0.761299, 0.829109, 1.}}

In[14]:= AbsoluteTiming[Table[g[x, 3, 2], {x, 0, 1, .1}]]

Out[14]= {0.127016, {0.00258519, 0.416409, 0.480731, 0.53073, 
  0.575419, 0.618365, 0.661898, 0.708357, 0.761299, 0.829109, 1.}}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.