Re: multiple outputs from compiled function
- To: mathgroup at smc.vnet.net
- Subject: [mg114698] Re: multiple outputs from compiled function
- From: Oliver Ruebenkoenig <ruebenko at wolfram.com>
- Date: Mon, 13 Dec 2010 03:53:24 -0500 (EST)
On Thu, 2 Dec 2010, Daniel Lichtblau wrote:
> Eric Michielssen wrote:
>> Thanks for the suggestion.
>>
>> I was thinking more about a routine that populates a huge sparse matrix, say
>> for finite element analysis. SparseArray does not work within Compile, and
>> that's understandable.
>>
>> So the next best thing would be to have a compiled function generate a long
>> list of positions ( pos = {pos1,pos2,pos3...} with posi = {n1,n2} ) and a
>> list of values ( val = {val1,val2,val3,...} ), and then construct the
>> SparseArray externally to a compiled function.
>>
>> But how do I get my compiled function to return both pos and val? Upon
>> reaching Return[{pos,val}], Mathematica reverts to the noncompiled function,
>> in essence starting over from scratch. (I can only think of a few not so
>> elegant solutions, none of which would apply in situations more complex than
>> the above).
>>
>> Eric
>
> Seems weird, but you might just do the setting via external variable(s).
> Here is a brief example. Notice that the list 'll' is not defined within
> Compile, but it is used in a Part assignment therein.
>
> In[1]:= ll = {2., 3., 4.};
>
> In[2]:= c = Compile[{{x}, {y}}, ll[[1]] = x; y];
>
> In[3]:= c[4.5, 5.6]
> Out[3]= 5.6
>
> In[4]:= ll
> Out[4]= {4.5, 3., 4.}
>
> Daniel Lichtblau
> Wolfram Research
>
>
To be quite honest I pretty much completely missed the point and
implications of Daniel's post and only "got it" when I received another
email from a colleague. So I thought I share what I leaned perhaps this is
useful to others too.
cf = Compile[{{n, _Integer}, {m, _Integer}},
Module[
{cpos = RandomSample[Range[n], m]},
Set[pos, cpos];
RandomReal[1, Length[cpos]]
]
];
The above compiled function computes some function and stores the result
in cpos. Then pos - which is a variable not in the Module scope - is set
to cpos and some other result is returned from the compiled function.
Wrapping the compiled function in, say, a Block
{valres, posres} = Block[{pos}, {cf[10, 5], pos}]
allows for two multiple values to be returned.
Map[Developer`PackedArrayQ, %]
if we look at this compiled function
<< "CompiledFunctionTools`"
CompilePrint[cf]
We see a call to MainEvaluate. Here the main cost is the copy of the cpos
data and in a big function that would be negligible.
It needs to copy the cpos since you could have something like this:
cf = Compile[{{n, _Integer}, {m, _Integer}},
Module[{cpos = RandomSample[Range[n], m]},
Set[pos, cpos];
cpos[[1]] = 1;
RandomReal[1, Length[cpos]]]];
This is mechanism that allows for multiple values to be returned from a
compiled function.
Hope this helps,
Oliver