1
$\begingroup$

I am trying to keep track of a calculation for visualization purposes ( I want to show to the user that calculation is in progress) . For that I use ProgressIndicator. However inside the paralleldo keeping track of the variable for the indicator makes the calculation much slower with respect to no-indicator. I wrote a "toy code" that mimics what I am doing. In this toy-code I am simply multiplying two arrays over and over again. Is there a way to make d run only in the main kernel and I simply multiply the with number of kernels, this will give me a rough idea.

myDummyF[nd_, np_] := Module[{mat, mat2, aI},

ns = 200;
mat = SetAccuracy[RandomReal[{-100, 100}, ns], nd];
             mat2 = SetAccuracy[RandomReal[{-200, 200}, ns], nd];
d = 0;
aI = ConstantArray[0, np];
SetSharedVariable[aI, d];

Time = AbsoluteTiming[
 If[nd <= 16,
  Monitor[Do[
    If[iC == 2, Print["Do Loop"]];
    aI[[iC]] = SetAccuracy[mat.(mat2/iC^0.5), nd], {iC, np}], 
   ProgressIndicator[Dynamic[iC/np]]],
  Monitor[ParallelDo[d++;
    If[iC == 2, Print[" ParallelDo Loop"]];
    aI[[iC]] = SetAccuracy[mat.(mat2/iC^0.5), nd];
    , {iC, np}],
   ProgressIndicator[Dynamic[d/np]]]]];

  Print["Do loop time = ", Time[[1]], ", np = ", np, ", nd = ", nd];
  aInum = Apply[Plus, (aI/np)];
  Print["Total = ", aInum];
  Return[aInum]];
  np = 1000;
  nd = 30;
  myDummyF[nd, np];

For do loop (not the parallel one) there is not performance issue. I know the that the performance hit coming from the overhead of carrying d. Is there another way of doing this? I don't need to keep track exactly just an idea would be fine.

Below is the same code without process indicator:

myDummyF[nd_, np_] := Module[{mat, mat2, aI},

ns = 200;
mat = SetAccuracy[RandomReal[{-100, 100}, ns], nd];

mat2 = SetAccuracy[RandomReal[{-200, 200}, ns], nd];

aI = ConstantArray[0, np];
SetSharedVariable[aI];
Time = AbsoluteTiming[
 If[nd <= 16,
  Do[
   If[iC == 2, Print["---------------------"]];
   If[iC == 2, Print["Do Loop", " nd= ", nd, " np= ", np]];
   aI[[iC]] = SetAccuracy[mat.(mat2/iC^0.5), nd], {iC, np}],
  ParallelDo[
   If[iC == 2, Print["---------------------"]];
   If[iC == 2, 
    Print[" ParallelDo Loop", " nd= ", nd, " np= ", np]];
   aI[[iC]] = SetAccuracy[mat.(mat2/iC^0.5), nd], {iC, np}]]];
  Print["Do loop time = ", Time[[1]]];
  aInum = Apply[Plus, (aI/np)];
  Print["Total = ", aInum];
  Print["---------------------"];
  Return[aInum]];
  np = 1000;
  nd = 30;
  myDummyF[nd, np];
$\endgroup$
  • $\begingroup$ Sometimes it is not worth to track an exact stage of the calculation and just show ProgressIndicator[ Appearance -> "Indeterminate"] before it is finished. p.s. are you sure every part of this code is essential to reproduce the problem? $\endgroup$ – Kuba Aug 11 '16 at 17:20
  • $\begingroup$ I gave the detail to show the performance difference between do and paralleldo. That is why I gave the details. With your suggestion, the progress indicator fills (%100) and after that calculation starts. That might be misleading. Is there a way to make d run only in the main kernel? $\endgroup$ – Erdem Aug 11 '16 at 18:11
  • $\begingroup$ Did you check the answers to the following questions? (1548), (15369), (74230), (86049) $\endgroup$ – Karsten 7. Aug 15 '16 at 18:22
  • $\begingroup$ @Karsten7. I did not see them before, I checked them. I think still the same suffering from the time of keep track of an variable in each kernel. Thnx $\endgroup$ – Erdem Aug 17 '16 at 13:57
2
$\begingroup$

I didn't want to bother about handling nd <= 16 as an extra condition and made some additional changes that increase the performance.

np = 1000;
nd = 30;

First the function without a ProgressIndicator as a reference:

dummyFKnoPI[nd_, np_] := Module[{mat, mat2, aI, ns = 200, time, aInum},
   mat = SetAccuracy[RandomReal[{-100, 100}, ns], nd];
   mat2 = SetAccuracy[RandomReal[{-200, 200}, ns], nd];
   aI = ConstantArray[0, np];

   time = AbsoluteTiming[
     Print[" Parallel Loop"];
     aI = ParallelTable[
       SetAccuracy[mat.(mat2/iC^0.5), nd],
       {iC, np}];
     ];
   Print["Loop time = ", time[[1]], ", np = ", np, ", nd = ", nd];
   aInum = Apply[Plus, (aI/np)];
   Print["Total = ", aInum];
   aInum];

dummyFKnoPI[nd, np*100];
 Parallel Loop
Loop time = 4.30922, np = 100000, nd = 30
Total = -392.25069339023950901292892012862

Now the function with a ProgressIndicator, but minimal inter kernel communication overload:

dummyFK[nd_, np_] := Module[{mat, mat2, aI, ns = 200, d = 0, dl, time, aInum},
   mat = SetAccuracy[RandomReal[{-100, 100}, ns], nd];
   mat2 = SetAccuracy[RandomReal[{-200, 200}, ns], nd];
   aI = ConstantArray[0, np];

   SetSharedVariable[d];
   ParallelEvaluate[dl = 0];

   time = AbsoluteTiming[
     Print[" Parallel Loop"];
     Monitor[
      aI = ParallelTable[
         If[Mod[dl++, 1000] == 0, d += 1000]; 
         SetAccuracy[mat.(mat2/iC^0.5), nd],
         {iC, np}];,
      ProgressIndicator[d/np]
      ]
     ];
   Print["Loop time = ", time[[1]], ", np = ", np, ", nd = ", nd];
   aInum = Apply[Plus, (aI/np)];
   Print["Total = ", aInum];
   aInum];

dummyFK[nd, np*100];
 Parallel Loop
Loop time = 4.5777, np = 100000, nd = 30
Total = -457.35153371159704445886973189772

When using d++ instead of If[Mod[dl++, 1000] == 0, d += 1000] the Loop time is 309.525.

$\endgroup$
  • 1
    $\begingroup$ Thank you for the help. I just made a little modification to scale the step of d with respect to np. Instead of directly putting 1000 , I did Ceilling[nd/75] this makes the lack between %100 status bar and calculation to finish to minimal. $\endgroup$ – Erdem Aug 21 '16 at 19:22

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.