Message Boards Message Boards

0
|
1448 Views
|
1 Reply
|
0 Total Likes
View groups...
Share
Share this post:

Evaluating Piecewise function defined inside Do loop is very slow

For a (relatively large) set of triplets $(i,l,m)$, I have a table of values representing a smooth function that is only continous at $x=0$. I am attempting to construct an interpolating function, by first interpolating their values to the "left" and "right" of $x=0$, and then stitiching the two solutions together via Piecewise (or If). As this must be done for each triplet $(i,l,m)$, I am doing this inside a Do loop. A self-contained example of this is the following code:

xmin = -2; xInterface = 0; xmax = 2;
xgrid = Range[xmin, xmax, 1/100];

Monitor[Do[
(*set up the table left and right of the interface*)
interfaceValue = RandomReal[{1, 10}];
myPolyLeft[x_] = 
RandomReal[{1, 3}] x^2 + RandomReal[{1, 10}] x + interfaceValue;
myPolyRight[x_] = 
RandomReal[{1, 3}] x^2 + RandomReal[{1, 10}] x + interfaceValue;
leftTable = 
Table[myPolyLeft[xmin + (xInterface - xmin) i/200], {i, 0, 200}];
rightTable = 
Table[myPolyRight[xInterface + (xmax - xInterface) i/200], {i, 0, 200}];

(*interpolate and stitch the solutions together*)
leftInterpol[i][l, m] = 
Interpolation[Transpose[{xgrid[[;; 201]], leftTable}]];
rightInterpol[i][l, m] = 
Interpolation[Transpose[{xgrid[[201 ;;]], rightTable}]];
fullInterpol[i][l, m][x_] = 
Piecewise[{{Evaluate[leftInterpol[i][l, m][x]], x < xInterface}, 
{Evaluate[rightInterpol[i][l, m][x]], x > xInterface}}, interfaceValue],
{i, 1, 10}, {l, 2, 40}, {m, -l, l}],
{i, l, m}]

What I am surprised to see is that, evaluating fullInterpol, for some parameters $(i,l,m)$, on a grid takes about 1000x longer than its left and right interpolants:

Table[rightInterpol[10][3, 2][xInterface + i (xmax - xInterface)/100], {i, 0, 100}]; // AbsoluteTiming
Table[leftInterpol[10][3, 2][xmin + i (xInterface - xmin)/100], {i, 0,100}]; // AbsoluteTiming
Table[fullInterpol[10][3, 2][xmin + i (xmax - xmin)/100], {i, 0, 100}]; // AbsoluteTiming
(* Timing Output: 0.000499, 0.000298, 0.451422  *)

Strangely, this seems to scale(!) with the range of parameters $(i,l,m)$, for example:

myNewFunc[10][3, 2][x_] = fullInterpol[10][3, 2][x];
Table[myNewFunc[10][3, 2][xmin + i (xmax - xmin)/100], {i, 0, 100}]; // AbsoluteTiming
(* Timing Output: 0.000272  *)

Finally, using pattern matching on each indices:

fullInterpol2[i_][l_, m_][x_] = 
 Piecewise[{{leftInterpol[i][l, m][x], x < xInterface}, {rightInterpol[i][l, m][x], x > xInterface}}, interfaceValue]

then timing is now quick:

Table[fullInterpol2[10][3, 2][xmin + i (xmax - xmin)/100], {i, 0, 100}]; // AbsoluteTiming
 (* Timing Output: 0.000346  *)

Can someone explain why this is happening?

POSTED BY: Patrick Bourg

Without checking your code:

The most time consuming constructs in an interpreting language are high level Do-loops and nested logical branchings by unstructrured Ifs.

Replace Do constructs by Mapping functions into arays.

Replace Piecewise and Which constructs by conditonal definitions where possible. If prcecison is not an issue, Replace slow evaluating functions by an Interpolation.

Try to avoid any overhead by logical tests, if they are not unavoidable in the current run.

POSTED BY: Roland Franzius
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract