1
$\begingroup$

For the following code, I could see the time it takes is proportional to the square of the c. Then if I go for c of a few thousands, it would take around a million seconds, which is too long (c=10 takes about 15 seconds). I could see if I replace the NIntegrate with a number, the speed increases dramatically. Would there be any way I can increase the speed significantly? Should I adjust the accuracy goal? Can I do parallel computation, although I think it won't be a solution?

u = 3;
c = 10;
Array[h, {u, c}];


v = Compile[{x, y}, 
   NIntegrate[Sin[Sqrt[x]/Abs[y + 0.1]*z], {z, 0, 1}], 
   "RuntimeOptions" -> "EvaluateSymbolically" -> False, 
   RuntimeAttributes -> {Listable}, Parallelization -> True, 
   CompilationTarget -> C];


Do[n = 1;
  If[j == 1,
   Do[h[j, n] = 
      NDSolveValue[{y''[x] == Cos[y[x]], y'[0] == 1, y[0] == n}, 
       y, {x, 0, 1}, 
       "Method" -> {"EquationSimplification" -> {Automatic, 
           "TimeConstraint" -> Infinity}}, AccuracyGoal -> 3], {n, c}];
   ,
   Do[h[j, n] = 
      NDSolveValue[{y''[x] == 
         Cos[y[x]] - (Sum[
            v[h[j - 1, n][x], h[j - 1, i][x]], {i, 1, c}])
        , y'[0] == 1, y[0] == n}, y, {x, 0, 1}, 
       "Method" -> {"EquationSimplification" -> {Automatic, 
           "TimeConstraint" -> Infinity}}, AccuracyGoal -> 3.], {n, 
      c}];
   ];
  , {j, 1, u}];
$\endgroup$
1
  • 1
    $\begingroup$ Can't you can replace that NIntegrate with the symbolic integral (Abs[0.1 + y] (1. - Cos[Sqrt[x]/Abs[0.1 + y]]))/Sqrt[x]? $\endgroup$ Nov 24, 2017 at 12:09

2 Answers 2

1
$\begingroup$

Since NIntegrate cannot be compiled, there is no point in compiling it. As aardvark2013 suggested, compile the symbolic expression of the integral with

v = With[{code = Integrate[Sin[Sqrt[x]/Abs[y + 0.1]*z], {z, 0., 1.}]},
  Compile[{{x, _Real}, {y, _Real}},
   code,
   "RuntimeOptions" -> "EvaluateSymbolically" -> False,
   RuntimeAttributes -> {Listable},
   Parallelization -> True,
   CompilationTarget -> "C"]
  ]

Note that I used {{x, _Real}, {y, _Real}} as first argument of Compile ({{x},{y}} would also work) instead of {x,y}.

$\endgroup$
4
  • $\begingroup$ Thanks. Compile the symbolic expression may crease the speed? Matlab would be better to increase the speed? $\endgroup$
    – user16308
    Nov 26, 2017 at 9:06
  • $\begingroup$ Yes, whenever it is about nonlinear number crunching, compiling speeds up things; usually by a factor 10 - 12 on a single core CPU when compiling through C-code. Wether Matlab would do it better? I doubt it. $\endgroup$ Nov 26, 2017 at 9:39
  • $\begingroup$ I am running on a server with 24 cores. The posted code is a simplified version of the actual code, to demonstrate the issue. Would there be other things I can do to increase the speed more? Parallelization would work? I heard parallelization cannot improve the speed of the NDSolveValue.. $\endgroup$
    – user16308
    Nov 26, 2017 at 10:59
  • $\begingroup$ That's hard to say without knowing the detail of your project (no, I don't want to know them). CCodeGenerator is somewhat the backend of Compile. No need for you to go there into detail. Honestly, have you tried to run your code with my suggestions? On my machine, it runs through within less than 0.05 seconds. $\endgroup$ Nov 26, 2017 at 11:16
0
$\begingroup$

I could see the computation becomes a lot faster (around 0.08 seconds). But if the function is not symbolically integrated (my project shown below is such a case),

u = 3;
c = 2;
it = 1;
Array[h, {u, c}];
T[u];

G[x_] := Sinc[x/2]^2;
FF[x_] := If[x == 0, -1, (-x*Cos[x] + Sin[x])/x^3];
dd[x_, y_] := x*Sqrt[G[x]*Cos[y]^2 + 1.];

w = With[{code = 
     Integrate[(Cos[2.*y] - Cos[x]) 0.5 (-1. + 
         3.*G[x] (Cos[y]^2/(G[x]*Cos[y]^2 + 1.)))*FF[dd[x, y]], {y, 
       0., 2 Pi}]}, 
   Compile[{{x, _Real}}, code, 
    "RuntimeOptions" -> "EvaluateSymbolically" -> False, 
    RuntimeAttributes -> {Listable}, Parallelization -> True, 
    CompilationTarget -> "C"]];

v = Compile[{x, y}, Sum[w[0.5 (x - y + i*2 Pi)], {i, -it, it}], 
   "RuntimeOptions" -> "EvaluateSymbolically" -> False, 
   RuntimeAttributes -> {Listable}, Parallelization -> True, 
   CompilationTarget -> C];

Do[n = 1;
  If[j == 1,
   T[j] = 
     AbsoluteTiming[
      Do[h[j, n] = 
        NDSolveValue[{y''[x] == Cos[y[x]], y'[0] == 1, y[0] == n}, 
         y, {x, 0, 1}, 
         "Method" -> {"EquationSimplification" -> {Automatic, 
             "TimeConstraint" -> Infinity}}, AccuracyGoal -> 3], {n, 
        c}]];
   ,
   T[j] = 
     AbsoluteTiming[
      Do[h[j, n] = 
         NDSolveValue[{y''[x] == 
            Cos[y[x]] - (Sum[
               v[h[j - 1, n][x], h[j - 1, i][x]], {i, 1, c}])
           , y'[0] == 1, y[0] == n}, y, {x, 0, 1}, 
          "Method" -> {"EquationSimplification" -> {Automatic, 
              "TimeConstraint" -> Infinity}}, AccuracyGoal -> 3.], {n,
          c}];];
   ]; Print[T[j]];
  , {j, 1, u}];

Can I still compile the symbolic expression of the integration? The program is stuck in defining the w.

Thank you.

$\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.