Re: Estimating Euler’s number (e) using probability: a fascinating approach

https://community.wolfram.com/groups/-/m/t/3140700

Implementations

Top-Level code

In[]:=
Clear[estimateE];​​estimateE[n_] :=​​ Module[{count,randomList,m},​​ randomList = RandomReal[{0, 1}, n];​​ count = Table[​​ Module[{prev = randomList[[i]], curr, c = 1},​​ While[​​ curr = RandomReal[];​​ curr < prev​​ ,​​ prev = curr;​​ c++​​ ];​​ c​​ ],​​ {i, 1, n}​​ ];​​ m = Mean[N[count]];​​ 1 + m​​ ]

(Old) Compile

In[]:=
estimateECompiledFunction = Compile{{n, _Integer}},​​ Module{count=0.,total=0.},​​ Do[​​ Module[{prev=RandomReal[],curr=0.,c=1},​​ While[​​ curr=RandomReal[];​​ curr>prev​​ ,​​ prev=curr;​​ c++;​​ ];​​ count+=c;​​ ],​​ {n}​​ ];​​ total = countn;​​ 1. + total​​ ,​​ CompilationTarget -> "C",​​ RuntimeAttributes -> {Listable},​​ Parallelization -> True,​​ RuntimeOptions->"Speed"​​
Out[]=
CompiledFunction
Argument count: 1
Argument types:
{_Integer}


FunctionCompile + DownValuesFunction

In[]:=
estimateECompiledCodeFunction1 = FunctionCompile[Typed[DownValuesFunction[estimateE], {"MachineInteger"} -> "MachineReal"]]
Out[]=
CompiledCodeFunction
Signature:
{Integer64}Real64


FunctionCompile + optimizations

In[]:=
estimateECompiledCodeFunction2 = FunctionCompile​​ Function{Typed[n, "MachineInteger"]},​​ Native`AbortInhibit @​​ Native`UncheckedBlock @​​ Module{count = 0., total = 0., randomList},​​ randomList = RandomReal[{0, 1}, n];​​ Do[​​ Module[{prev = randomList[[i]], curr = 0., c = 1},​​ While[​​ curr = RandomReal[];​​ curr > prev​​ ,​​ prev = curr;​​ c += 1;​​ ];​​ count += c;​​ ],​​ {i, n}​​ ];​​ total = count  n;​​ 1. + total​​ ​​ ​​
Out[]=
CompiledCodeFunction
Signature:
{Integer64}Real64


Timings

In[]:=
Clear[computeEstimations]​​computeEstimations[estimateFun_] :=​​ Module[{res},​​ res = AbsoluteTiming[<|Table[<|i -> estimateFun[10^i]|>, {i, 4, 8}]|>];​​ <|"Data" -> res[[2]], "AbsoluteTiming" -> Quantity[res[[1]], "Seconds"]|>​​ ];
In[]:=
res=Association@MapApply[​​(Print["Computing using ",#1,"..."];​​#1->computeEstimations[#2])&,​​{​​{"Top-Level",estimateE},​​{"Old Compile",estimateECompiledFunction},​​{"New Compile",estimateECompiledCodeFunction1},​​{"New Compile + Optimizations",estimateECompiledCodeFunction2}​​}​​];
Computing using Top-Level...
Computing using Old Compile...
Computing using New Compile...
Computing using New Compile + Optimizations...
In[]:=
ListPlot[res[[All,"Data"]],AxesLabel->{"10^","Estimate"},PlotLegends->Keys[res]]
Out[]=
Top-Level
Old Compile
New Compile
New Compile + Optimizations
In[]:=
Dataset[res[[All,"AbsoluteTiming"]]]
Out[]=
Top-Level
15.7112s
Old Compile
6.14201s
New Compile
5.61131s
New Compile + Optimizations
4.10656s