1
$\begingroup$

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?

$\endgroup$

2 Answers 2

6
$\begingroup$

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.

$\endgroup$
5
$\begingroup$

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.
$\endgroup$
1
  • $\begingroup$ Thanks! However, my question just illustrates the basic problem I deal with every time when considering vector definitions. $\endgroup$ Commented Oct 26, 2022 at 11:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.