MathGroup Archive 2010

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

Search the Archive

Re: Pass by reference for compiled functions

  • To: mathgroup at smc.vnet.net
  • Subject: [mg114317] Re: Pass by reference for compiled functions
  • From: Leonid Shifrin <lshifr at gmail.com>
  • Date: Wed, 1 Dec 2010 02:09:27 -0500 (EST)

Hi Eric,

You can  also kind of emulate pass-by-reference by inlining compiled
functions, but this will only
work if your caller function  is also Compiled, and all the ingredients are
compiled. Here is an example:

Clear[primeQ ];
primeQ  =
  Compile[{{n, _Integer}},
   Total[1 - Unitize@Mod[n, Range[2, IntegerPart[Sqrt[n]] + 1]]] ==
    0];

ClearAll[primes];
primes =
  Compile[{},
   list = Select[list, primeQ],
   CompilationOptions -> {"InlineExternalDefinitions" -> True,
     "InlineCompiledFunctions" -> True}];

test =
  Compile[{},
   Module[{list = Range[100000]},
    primes[];
    list],
   CompilationOptions -> {"InlineExternalDefinitions" -> True,
     "InlineCompiledFunctions" -> True}];


In[87]:=
test[]//Short//Timing
Out[87]=
{0.828,{1,3,5,7,11,13,17,19,23,29,31,<<9570>>,99871,99877,99881,99901,99907,99923,99929,99961,99971,99989,99991}}

Note that the variable <list> has not been defined in <primes>, so <primes>
works essentially
like a macro. At the end, everything is inlined inside <test>, and for this
to work, this must
have happened before the variables are bound. So, we actually do change the
variable <list>
defined in <test>, even though it is done inside <primes>. At the same time,
the global <list>
does not acquire any value. But this would not work if <primes> would not
have entirely compiled -
for instance, if you change primeQ (compiled) to PrimeQ (uncompiled,
built-in, external call).

You can inspect the final compiled code for <test> by calling test[[6]] and
see that it indeed
did compile completely to byte-code. In particular, you should be able to
compile to C if needed.
So, this is not the true pass-by-reference since no arguments are passed
explicitly, but this seems
to give similar means of combining larger programs from smaller pieces
without copying data, more
like templates. I am not sure about the status of this "technique", I just
discovered it recently - this
looks more like a hack to me, but it seems to work.

Hope this helps.

Regards,
Leonid


On Mon, Nov 29, 2010 at 2:10 PM, Eric Michielssen
<emichiel at eecs.umich.edu>wrote:

> For noncompiled functions, one can pass arguments "by reference" and then
> modify them inside the routine by assigning the function the attribute
> HoldAll.
>
> This does not work for compiled functions: it does not appear possible to
> modify arguments to compiled functions, even if they are passed as "global
> variables". That is, Mathematica responds to
>
> Myfunction = Compile[
> {{var1,_Real}},
> Module[{},
> Modify var 1 or var2;
> Return[]], {var2,_Real}];
>
> With
>
> Compile::argset: The assignment to var1 is illegal; it is not valid to
> assign a value to an argument. >>  And something similar for var2.
>
> HoldAll does not seem to apply here...
>
> This makes it memory-inefficient to modify large arrays in compiled
> functions, as one would have to operate on a copy of the array.
>
> Is there a workaround in Mathematica 8?
>
> Eric Michielssen
>
>
>
>


  • Prev by Date: Re: SelectionMove[] busted with InputField and DockedCells?
  • Next by Date: Re: Why are my 3D plots blue?
  • Previous by thread: Re: SelectionMove[] busted with InputField and DockedCells?
  • Next by thread: Re: Why are my 3D plots blue?