2
$\begingroup$

How can I modify this code in order to run in parallel? (It's some part of my main code)

LogNeg = {};
Do[LNeg = 0;
Do[Do[
  A = {{CoMat[[2*i - 1, 2*i - 1]], 
    CoMat[[2*i - 1, 2*i]]}, {CoMat[[2*i, 2*i - 1]], 
    CoMat[[2*i, 2*i]]}};

  B = {{CoMat[[2*j - 1, 2*j - 1]], 
    CoMat[[2*j - 1, 2*j]]}, {CoMat[[2*j, 2*j - 1]], 
    CoMat[[2*j, 2*j]]}};

  F = {{CoMat[[2*i - 1, 2*j - 1]], 
    CoMat[[2*i - 1, 2*j]]}, {CoMat[[2*i, 2*j - 1]], 
    CoMat[[2*i, 2*j]]}};

  S = ArrayFlatten[{{A, F}, {Transpose[F], B}}];

  v = eta /. 
   Solve[eta^4 - (Det[A] + Det[B] - 2*Det[F])*eta^2 + Det[S] == 0];

  LNeg += -Log2[Min[Abs[v], 1]], {j, i + 1, M}], {i, 1, M}];

  AppendTo[LogNeg, LNeg], {t, 0, tMax}];

I've used ParallelDo[], but It doesn't work. Main code: https://ufile.io/cmjj6

Thank you in advance

$\endgroup$
13
  • 1
    $\begingroup$ We cannot run this code without CoMat. Where exactly did you use ParallelDo? $\endgroup$
    – ZaMoC
    Nov 9, 2018 at 7:56
  • $\begingroup$ @J42161217 CoMat is a 2M*2M square matrix of interpolating Functions. It's made by solving ODEs. The code is a big one, anyway, It's what I embedded above. $\endgroup$
    – Ghaem
    Nov 9, 2018 at 8:16
  • $\begingroup$ Did you try to substitute only the outer Do? $\endgroup$
    – ZaMoC
    Nov 9, 2018 at 8:23
  • $\begingroup$ Yes, I did; Both outer Do' separately. $\endgroup$
    – Ghaem
    Nov 9, 2018 at 8:25
  • 1
    $\begingroup$ What exactly do you mean by "it doesn't work"? Could you add the exact code you tried and the error it produced to the question? $\endgroup$
    – Lukas Lang
    Nov 9, 2018 at 8:26

1 Answer 1

1
$\begingroup$

Still not parallelized, but tremendously faster. Most important are:

  • The matrix CoMat is evaluated only once for each t. Inparticular, CoMat2[t] is explicitly defined as a function t to gai control over evaluation; and it returns the matrix CoMat already nicely partitioned for easy access.
  • The function sol which solves the symbolic equation once and the time of definition.

This makes the execution ten times faster.

CoMat2[t_] = Partition[
   First[Cov[t] /. 
     NDSolve[{Join[DiffEq, InitialCond]}, Cov[t], {t, 0, tMax}]],
   {2, 2}, {2, 2}];
sol[p_, q_] = N[η /. Solve[η^4 - p η^2 + q == 0, η]];
result = Table[
     Mat = Developer`ToPackedArray[CoMat2[t]];
     Block[{A, detA, B, F, S},
      Sum[
       A = Mat[[i, i]];
       detA = Det[A];
       Sum[
        B = Mat[[j, j]];
        F = Mat[[i, j]];
        S = ArrayFlatten[{{A, F}, {Transpose[F], B}}];
        -Log2[Min[Abs[sol[(detA + Det[B] - 2*Det[F]), Det[S]]], 1]],
        {j, i + 1, M}],
       {i, 1, M}]
      ],
     {t, 0., tMax}]; // AbsoluteTiming // First

0.327722

Edit

I cannot speed up the InterpolatingFunctions, but the rest can be made much faster (and parallelized) with Compile:

Block[{MAT, i, j, A, B, F, S, vcode},
  A = {
    {Compile`GetElement[MAT, 2 i - 1, 2 i - 1], Compile`GetElement[MAT, 2 i - 1, 2 i]},
    {Compile`GetElement[MAT, 2 i, 2 i - 1], Compile`GetElement[MAT, 2 i, 2 i]}
    };
  B = {
    {Compile`GetElement[MAT, 2 j - 1, 2 j - 1], Compile`GetElement[MAT, 2 j - 1, 2 j]},
    {Compile`GetElement[MAT, 2 j, 2 j - 1], Compile`GetElement[MAT, 2 j, 2 j]}
    };
  F = {
    {Compile`GetElement[MAT, 2 i - 1, 2 j - 1], Compile`GetElement[MAT, 2 i - 1, 2 j]},
    {Compile`GetElement[MAT, 2 i, 2 j - 1], Compile`GetElement[MAT, 2 i, 2 j]}
    };
  S = ArrayFlatten[{{A, F}, {Transpose[F], B}}];
  vcode = sol[(Det[A] + Det[B] - 2*Det[F]), Det[S]];
  
  cf = With[{code = vcode},
    Compile[{{MAT, _Real, 2}, {M, _Integer}},
     Block[{LNeg = 0.},
      Do[Do[
        LNeg -= Log2[Min[Abs[code], 1.]],
        {j, i + 1, M}], {i, 1, M}];
      LNeg
      ],
     CompilationTarget -> "C",
     RuntimeAttributes -> {Listable},
     Parallelization -> True,
     RuntimeOptions -> "Speed"
     ]
    ]
  ];

Now the computations:

CoMat[t_] = 
  First[Cov[t] /. 
    NDSolve[{Join[DiffEq, InitialCond]}, Cov[t], {t, 0, tMax}]];
Mat = Developer`ToPackedArray[
    Table[CoMat[t], {t, 0., tMax}]]; // AbsoluteTiming
result2 = cf[Mat, M]; // AbsoluteTiming // First
Max[Abs[result - result2]]

0.123596

0.000423

6.24386*10^-11

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