1

Consider a vector

vec[x_,y_,z_]={x^0.5*y^0.1,y^0.3*z^0.1,z^2*x*y};

I need to calculate, say, a table with vector values for the coordinates

tabscord=RandomReal[{0, 1}, {10^7, 3}];

I would like to use Compile. This is my realization:

tabcompiled = 
 Hold@Compile[{{tabscord, _Real, 2}}, 
   Table[vec[tabscord[[i]][[1]], tabscord[[i]][[2]], 
     tabscord[[i]][[3]]], {i, 1, Length[tabscord], 1}], 
   CompilationTarget -> "C", RuntimeOptions -> "Speed"] /. 
  DownValues@vec//ReleaseHold

However, it says

CompiledFunction::cfse: Compiled expression {0.815274,0.188035,0.433407} should be a machine-size real number.

To avoid this problem, I need to define first the coordinates of the vector, say,

vecx[x_,y_,z_]=vec[x,y,z][[1]];
vecy[x_,y_,z_]=vec[x,y,z][[2]];
vecz[x_,y_,z_]=vec[x,y,z][[3]];

And then

tabcompiled = Hold@Compile[{{tabscord, _Real, 2}}, Table[{vecx[tabscord[[i]][[1]], tabscord[[i]][[2]], tabscord[[i]][[3]]],vecy[tabscord[[i]][[1]], tabscord[[i]][[2]], tabscord[[i]][[3]]],vecz[tabscord[[i]][[1]], tabscord[[i]][[2]], tabscord[[i]][[3]]]}, {i, 1, Length[tabscord], 1}], CompilationTarget -> "C", RuntimeOptions -> "Speed"] /. DownValues@vecx/.DownValues@vecy/.DownValues@vecz//ReleaseHold

Could you please tell me whether it is possible to avoid defining separate coordinates of vec if using Compile?

John Taylor
  • 5,701
  • 2
  • 12
  • 33

2 Answers2

6

Using a pure function

vec = Function[{x,y,z},{x^0.5*y^0.1,y^0.3*z^0.1,z^2*x*y}];

and inlining works:

f = Compile[{{x,_Real,2}},
      Table[vec[x[[i,1]],x[[i,2]],x[[i,3]]],{i,1,Length[tabscord]}],
      CompilationTarget->"C",RuntimeOptions->"Speed",
      CompilationOptions->{"InlineExternalDefinitions"->True}
];

tabscord=RandomReal[{0,1},{10^7,3}]; f[tabscord] (* takes about 3 seconds *)

See this answer for inlining definitions.

user293787
  • 11,833
  • 10
  • 28
5

I understand that the question is about Compile, but this is a case where it is easy to get fast code without compiling: Assuming OP's definitions

vec[x_,y_,z_]={x^0.5*y^0.1,y^0.3*z^0.1,z^2*x*y};
tabscord=RandomReal[{0,1},{10^7,3}];

one can use

Transpose[vec@@Transpose[tabscord]]
(* takes about 1.3 seconds *)

Comments:

  • The inner transpose turns the three big columns into three big rows, and vec@@ then means that vec is called with x equal to the entire first column of tabscord, y equal to the second column, z the third column.
  • Therefore, z^2*x*y is called with x, y, z equal to vectors of length $10^7$ which we can be sure is already optimized and we do not have to compile.
  • Always make sure that arrays are packed. Here they are.
user293787
  • 11,833
  • 10
  • 28
  • Thanks! However, my question just illustrates the basic problem I deal with every time when considering vector definitions. – John Taylor Oct 26 '22 at 11:40