5
$\begingroup$

Consider the following function:

 function[x_, y_] = If[x < Exp[y], Sqrt[1 - x/Exp[y]], 0];
functionTotal1[x_] = Sum[function[x, 0.02*j], {j, 0, 4*10^5, 1}];

Calling this function is very slow:

AbsoluteTiming[functionTotal1[2]]

gives 1.5 seconds. This is probably related to If condition. What is a possible way to make calling faster, apart from making an interpolation?

$\endgroup$
1
  • $\begingroup$ If you have a multicore CPU you can use ParallelSum. $\endgroup$
    – vi pa
    Commented Dec 20, 2019 at 10:45

2 Answers 2

13
$\begingroup$

Using Ramp and vectorized operations:

y = -.02 Range[0, 4 10^5];
Total @ Sqrt[Ramp[1 - 2 Exp[y]]] //AbsoluteTiming

{0.018728, 399935.}

$\endgroup$
1
  • 1
    $\begingroup$ H o l y c o w ! :-) $\endgroup$
    – Mr.Wizard
    Commented Dec 20, 2019 at 1:27
4
$\begingroup$

On my machine

function[x_, y_] := If[x < Exp[y], Sqrt[1 - x/Exp[y]], 0];
functionTotal1[x_] := Sum[function[x, 0.02*j], {j, 0, 4*10^5, 1}];
RepeatedTiming[functionTotal1[2]]

{6.631, 399935.}

Here are a few things that I noticed that speed up evaluation.

Each term is real or imaginary

First we see that if $x \leq \exp(y)$, then $\sqrt{1-x e^{-y}}$ is real, and if $x > \exp(y)$, then $\sqrt{1-x e^{-y}}$ is strictly imaginary. Therefore, if we get rid of the If and ignore all the imaginary terms (effectively setting each term where $x > \exp(y)$ to zero)

f[x_, y_] := Sqrt[1 - x/Exp[y]]
ftot[x_] := Re@Sum[f[x, 0.02*j], {j, 0., 4.*10^5}]
RepeatedTiming[ftot[2]]

{5.3, 399935.}

Vectorization and packed arrays

With the thought of restructuring the Sum into a Dot to utilize vectorization, we rewrite the term $\sqrt{1-x e^{-y}}$ into a product of terms as $e^{-y/2} \sqrt{e^y-x}$. Then, skipping the declaration of the "term" function, the sum can be written as

ftotdot[x_] := Dot @@ (Transpose@Table[{Exp[-0.02 y/2], Sqrt[Exp[0.02 y] - x]}, {y, 0., 4.*10^5}]) // Re
ftotdot[2] // RepeatedTiming

{2.91, 399935.}

Then, since Exp and arithmetic operators are vectorized we can replace the Table with an evaluation of the packed array in Range.

ftotdot2[x_] := Exp[-#/2].Sqrt[Exp[#] - x] &[0.02 Range[0., 4.*10^5]]) // Re
ftotdot2[2] // RepeatedTiming

{2.3, 399935.}

Further improvements may include the use of SparseArrays, Compile, even just parallelization.

$\endgroup$

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.