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
    $\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$ – aardvark2012 Nov 24 '17 at 12:09
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$
  • $\begingroup$ Thanks. Compile the symbolic expression may crease the speed? Matlab would be better to increase the speed? $\endgroup$ – user16308 Nov 26 '17 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$ – Henrik Schumacher Nov 26 '17 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 '17 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$ – Henrik Schumacher Nov 26 '17 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, privacy policy and cookie policy

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