Re: Compiled function slowdown

*To*: mathgroup at smc.vnet.net*Subject*: [mg86701] Re: [mg86682] Compiled function slowdown*From*: Daniel Lichtblau <danl at wolfram.com>*Date*: Wed, 19 Mar 2008 05:22:25 -0500 (EST)*References*: <200803180950.EAA18644@smc.vnet.net>

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[] construct. 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}, While[True, u = RandomReal[]; If[u < stepTotAccum, stats = 1 + 4*Floor[u/pTile]; cand = (u - dxTable[[stats + 2]])/dxTable[[stats + 1]] + dxTable[[stats]]; If[RandomReal[]*dxTable[[stats + 3]] < fComp[cand], res = cand*(-1)^RandomInteger; Break[]; ], cand = e1[u]; If[e2[RandomReal[], cand, area] < fComp[cand], res = cand*(-1)^RandomInteger; Break[]; ] ]; ];], {{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: http://forums.wolfram.com/mathgroup/archive/2003/Jun/msg00541.html (I think the recommendation in the brief note at that URL is an underutilized gem.) Daniel Lichtblau Wolfram Research

**References**:**Compiled function slowdown***From:*mm1q <epv001@lvc.edu>