5

Consider a simple function

g[x_,y_,z_] := x + y + z; 

(indeed, any multivariate function g will illustrate the same thing). And suppose we're given a list of list of the form,

list = { {1,2,3}, {4,5,6} }

Without using Compile, if I want a result of the form { g[1,2,3], g[4,5,6] }, I can use Apply to get,

resultlist = g @@@ list 

Question: Suppose that I want to write a compiled, listable, version of g, such that,

g[list] = { g[1,2,3], g[4,5,6] } 

How would we achieve the same result? I'd attempted to write a Listable of the form,

compileG = Compile[ {x,y,z}, 
                     x + y + z, 
                     RuntimeAttributes -> {Listable}
                   ] 

then it'll give me the error CompiledFunction::cfct: Number of arguments 1 does not match the length 3 of the argument template. Of course, in this circumstance, I know that compileG @@@ list will still work.

However, in the actual application I have in mind, the g function will be involved and list is quite large, and hence, I want to take advantage of these options RuntimeAttributes -> {Listable}, CompilationTarget -> "C", Parallelization -> True (which, at least according to here http://www.walkingrandomly.com/?p=3635, gives a very significant speed boost.)

user32416
  • 1,203
  • 8
  • 14
  • 3
    You are not specific the argument list correctly (in the Compile function). Open up the docs and see the right way to do it or read the WalkingRandomly article thoroughly. – Sektor Aug 18 '15 at 08:31
  • Can you please be more specific as to where I didn't setup my Compile function correctly? I'd read through the documentations (https://reference.wolfram.com/language/ref/RuntimeAttributes.html) and the WalkingRandomly article. The toy function compileG will indeed compute – user32416 Aug 18 '15 at 08:42
  • 4
    compileG = Compile[{{x, _Real, 1}}, Total[x], RuntimeAttributes -> {Listable}] then compileG[{{1, 2, 3}, {4, 5, 6}}] prints {6., 15.} – Sektor Aug 18 '15 at 09:07
  • @Sektor Thanks! This is helpful. – user32416 Aug 18 '15 at 18:30
  • You are welcome ! – Sektor Aug 18 '15 at 18:32
  • I'm voting to reopen, since the behavior of the comment-answer by Sektor is very much not obvious. Consider g[x_List] := Total[x];SetAttributes[g,Listable] instead. We would get {{g[1],g[2],g[3]},{g[4],g[5],g[6]}} – LLlAMnYP Dec 07 '16 at 12:01
  • @LLlAMnYP From the docs for RuntimeAttributes: "If a compiled function with Listable attribute receives any arguments with higher rank than specified, the function will thread over these arguments." See this and this for more discussion. – Michael E2 Mar 09 '17 at 15:08
  • The two linked discussions are very lengthy and do briefly mention this behavior of compiled functions, but don't (I only had time to skim through) go into great depth. I think, this is worth a question of its own, unless this is already covered here. – LLlAMnYP Mar 09 '17 at 15:29
  • 1
    BTW, alternate solution is compileG = Compile[{x, y, z}, x + y + z, RuntimeAttributes -> {Listable}]; compileG[{1, 4}, {2, 5}, {3, 6}] – LLlAMnYP Mar 09 '17 at 15:30
  • @LLlAMnYP I just thought you (and others) might be interested. Somewhere there is a comment by Leonid about the difference in how listability is implemented for symbols and for compiled functions. It's interesting, but I couldn't find it. – Michael E2 Mar 10 '17 at 12:53
  • @MichaelE2 I am interested, so much, that I'll create this question as soon as I can. – LLlAMnYP Mar 10 '17 at 14:01

2 Answers2

4

Sector has given a solution for the specific example in the comment above:

compileG = Compile[{{x, _Real, 1}}, Total[x], RuntimeAttributes -> {Listable}] 
compileG[{{1, 2, 3}, {4, 5, 6}}]

However, whether this solution is extensible or not really depends on your actual code, you'd better add more details to your question if it doesn't help.

xzczd
  • 65,995
  • 9
  • 163
  • 468
0

However, in the actual application I have in mind, the g function will be involved and list is quite large, and hence, I want to take advantage of these options RuntimeAttributes -> {Listable}, CompilationTarget -> "C", Parallelization -> True (which, at least according to here http://www.walkingrandomly.com/?p=3635, gives a very significant speed boost.)

The Listable attribute in the link works slightly differently.

g[x_,y_,z_] := x + y + z; (* Plus is Listable by default *)

compileG = Compile[{x,y,z}, x + y + z, RuntimeAttributes -> {Listable}]

list = {{1,2,3}, {4,5,6}};

Neither of this works:

g[list]
compileG[list]

Having listability means being able to thread over lists.

Thread[{a, b}~g~{c, d}]
(* {g[a, c], g[b, d]} *)

Consequentially, Listable enables this to work:

compileG[xList, yList, zList]

For example:

{xList, yList, zList} = RandomReal[10., {3, 10}]
(* {
 {9.89594, 4.63021, 2.29814, 8.72035, 5.96282, 2.72297, 7.83348, 1.47251, 8.12116, 9.33473},
 {1.67636, 6.0282,  5.47119, 9.67162, 5.29997, 2.25684, 4.47208, 8.55757, 8.19018, 8.35372},
 {1.10912, 0.87434, 4.36243, 9.76855, 9.60058, 8.8579, 0.861787, 1.60515, 0.0182481, 0.795345}
} *)
compileG[xList, yList, zList]
(* {12.6814, 11.5328, 12.1318, 28.1605, 20.8634, 13.8377, 13.1673, 11.6352, 16.3296, 18.4838} *)
LLlAMnYP
  • 11,486
  • 26
  • 65