I am wondering whether the speed of compilation for the new compiler can be improved.
Here are the results from my test.
Consider the following function for generating a random draw from a gamma distribution
ablRanGamma[alpha_, beta_] :=
Module[
{d, c, x = 0.0, v = 0.0, u, cond},
d = alpha - 1.0/3.0;
c = 1.0/Sqrt[9.0*d];
cond = 1;
While[cond == 1,
v = -1.0;
While[v <= 0.0,
x = RandomVariate[NormalDistribution[0, 1]];
v = 1.0 + c*x;
];
v = v^3;
u = RandomReal[];
If[u > 1. - 0.0331*x^4 &&
Log[u] > 0.5*x^2 + d*(1.0 - v + Log[v]), cond = 1, cond = 0];
];
beta*d*v
]
The old compiler technology can be used to compile the function to C, as follows
ablRanGammaC = Compile[{{alpha, _Real}, {beta, _Real}},
Module[
{d, c, x = 0.0, v = 0.0, u, cond},
d = alpha - 1.0/3.0; c = 1.0/Sqrt[9.0*d]; cond = 1;
While[cond == 1,
v = -1.0;
While[v <= 0.0,
x = RandomVariate[NormalDistribution[0, 1]];
v = 1.0 + c*x;
];
v = v^3;
u = RandomReal[];
If[
u > 1. - 0.0331*x^4 && Log[u] > 0.5*x^2 + d*(1.0 - v + Log[v]),
cond = 1, cond = 0];
];
beta*d*v
],
CompilationTarget -> "C"
];
This results in a significant improvement is speed, as expected.
In[10]:= AbsoluteTiming[Mean@Table[ablRanGamma[2.1, 3.2], {500000}]]
Out[10]= {11.7353, 6.71994}
In[7]:= AbsoluteTiming[Mean@Table[ablRanGammaC[2.1, 3.2], {500000}]]
Out[7]= {0.142951, 6.72236}
Now moving to the new compiler. First, RandomVariate[NormalDistribution[0,1]]
cannot be compiled directly, so we need to use a KernelFunction. We create two functions to get random normal draws, one compiled and the other not.
f1[m_, s_] := RandomVariate[NormalDistribution[m, s]]
f1C = Compile[{{m, _Real}, {s, _Real}},
RandomVariate[NormalDistribution[m, s]],
CompilationTarget -> "C"
];
Then we can use these as KernelFunctions using the new compiler. Consider the function which uses f1.
ablRanGammaN1 = FunctionCompile[
Function[{Typed[alpha, "Real64"], Typed[beta, "Real64"]},
Module[
{d, c, x = 0.0, v = 0.0, u, cond,
f1 = Typed[
KernelFunction[f1], {"Real64", "Real64"} -> "Real64"]},
d = alpha - 1.0/3.0; c = 1.0/Sqrt[9.0*d]; cond = 1;
While[cond == 1,
v = -1.0;
While[v <= 0.0,
x = f1[0.0, 1.0];
v = 1.0 + c*x;
];
v = v^3;
u = RandomReal[];
If[
u > 1. - 0.0331*x^4 && Log[u] > 0.5*x^2 + d*(1.0 - v + Log[v]),
cond = 1, cond = 0];
];
beta*d*v
]
]
];
Its performance is
In[8]:= AbsoluteTiming[Mean@Table[ablRanGammaN1[2.1, 3.2], {500000}]]
Out[8]= {2.46856, 6.72463}
This can be improved by using f1C instead of f1 as a kernel function.
ablRanGammaN2 = FunctionCompile[
Function[{Typed[alpha, "Real64"], Typed[beta, "Real64"]},
Module[
{d, c, x = 0.0, v = 0.0, u, cond,
f1 = Typed[
KernelFunction[f1C], {"Real64", "Real64"} -> "Real64"]},
d = alpha - 1.0/3.0; c = 1.0/Sqrt[9.0*d]; cond = 1;
While[cond == 1,
v = -1.0;
While[v <= 0.0,
x = f1[0.0, 1.0];
v = 1.0 + c*x;
];
v = v^3;
u = RandomReal[];
If[
u > 1. - 0.0331*x^4 && Log[u] > 0.5*x^2 + d*(1.0 - v + Log[v]),
cond = 1, cond = 0];
];
beta*d*v
]
]
];
We now have
In[9]:= AbsoluteTiming[Mean@Table[ablRanGammaN2[2.1, 3.2], {500000}]]
Out[9]= {0.81675, 6.72306}
This is clearly better than the uncompiled function, but still is significantly slower than when we compile to C using the old technology. Can anybody explain why this is the case. In my experiments, this does not seem to be due to the overhead of using a kernel function. The C compiled code appears to be faster than the machine compiled code for the new technology.