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
>
>
>
>