MathGroup Archive 2008

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Compiled function slowdown

mm1q wrote:
> Hello,
> In a program I'm currently working on, I need to loop through a function ~100,000 times.  I thought I'd try compiling it to save on time.  However, it takes more than 10 times longer to run than the uncompiled (module) version.  Are there any general guidelines as to when a compiled function will be slower than its uncompiled counterpart in Mathematica (such as with the use of many conditional statements)?  I've included my function below (sorry if it's a mess; e1, e2 and fComp are very simple compiled functions), though a general response to the above question would be just fine.  Thanks!
> generator = Compile[{stepTotAccum_Real, {dxTable, _Real, 1},
> pTile_Real, area_Real},
>       Do[
>         While[True,
>             u = Random[];
>             If[ u < stepTotAccum,
>               stats = 1 + 4*Floor[u/pTile];
>               cand = (u - dxTable[[stats + 2]])/dxTable[[stats + 1]] + 
>             dxTable[[stats]];
>               If[Random[]*dxTable[[stats + 3]] < fComp[cand], 
>                 Return[cand * (-1)^Random[Integer]]
>                 ];
>               ,
>               cand = e1[u];
>               If[e2[Random[], cand, area] < fComp[cand],
>                 Return[cand * (-1)^Random[Integer]]
>                 ];
>               ];
>             ];
>         ]
>       ];

There are several issues. First, I doubt Compile will recognize your 
scalar argument specification constructs such as pTile_Real. It will, 
however, handle {pTile,_Real}.

Second, it will need to know the return types of your external 
functions. This information can be passed in the optional third argument 
to Compile.

Third, you have variables that are not localized, hence not amenable to 
type inferencing. They can and should be localized within a Module[] 

Fourth, Compile is not able to assess the "return" type from your loop 
exits. While this might be a weakness in the type inferencing 
implementation code, nonetheless you will need to change the code 
structure a bit to have an explicit return value outside that loop.

Fifth, you have a Do that is neither needed nor correctly constructed 
(Do takes an explicit iterator).

Here is a rewritten variant that might work better.

generator =
  Compile[{{stepTotAccum, _Real}, {dxTable, _Real,
     1}, {pTile, _Real}, {area, _Real}},
   Module[{stats, u, cand, res},
      u = RandomReal[];
      If[u < stepTotAccum,
       stats = 1 + 4*Floor[u/pTile];
       cand = (u - dxTable[[stats + 2]])/dxTable[[stats + 1]] +
       If[RandomReal[]*dxTable[[stats + 3]] < fComp[cand],
        res = cand*(-1)^RandomInteger;
       cand = e1[u];
       If[e2[RandomReal[], cand, area] < fComp[cand],
        res = cand*(-1)^RandomInteger;
   {{e1, _Real}, {e2, _Real}, {fComp, _Real}}]

If those functions e1, e2, and fComp are "inlined" I would guess you 
will get a further speed improvement. To see how to do this you might check:

(I think the recommendation in the brief note at that URL is an 
underutilized gem.)

Daniel Lichtblau
Wolfram Research

  • Prev by Date: Re: Using a logical Or in the function definition
  • Next by Date: Re: How to consider BrowserCategories in Version 6.0?
  • Previous by thread: Compiled function slowdown
  • Next by thread: Re: Compiled function slowdown