-1
$\begingroup$

I am running a lengthy do loop and I wish to use Parallelize so that multiple kernels are used. What I do in the loop is update a set of counters that report the final results. The counters do not work when using Parallelize. How can I fix this if possible. Here is some sample code

Ncases=0; NS5=0; NA5=0; NF20=0; ND5=0; NC5=0; Nreducible=0; Nirreducible=0; 
Parallelize[Do[Ncases++; test=x^5+rx^3+sx^2+t(x+1); 
If[IrreduciblePolynomialQ[test],Nirreducible++;group=QuinticGaloisGroup[test]; 
If[group==SymmetricGroup[5],NS5++]; If[group==AlternatingGroup[5],NA5++]; 
If[group==MetacyclicGroup[20],NF20++]; If[group==DihedralGroup[10],ND5++]; 
If[group==CyclicGroup[5],NC5++],Nreducible++],{r,-10,+10},{s,-10,+10},{t,-10,+10‌​}]];

Where IrreduciblePolynomialQ returns true if the polynomial is reducible. The function QuinticGaloisGroup determines the Galois group. So using a generic polynomial as the test polynomial I am counting the cases. The counters are not being incremented. I have many examples like this where the calculation times becomes hours and days.

$\endgroup$
  • $\begingroup$ Please give skeleton example code so we can help. $\endgroup$ – David G. Stork Nov 13 '15 at 23:43
  • $\begingroup$ Ncases=0; NS5=0; NA5=0; NF20=0; ND5=0; NC5=0; Nreducible=0; Nirreducible=0; Parallelize[Do[Ncases++; test=x^5+rx^3+sx^2+t(x+1); If[IrreduciblePolynomialQ[test],Nirreducible++;group=QuinticGaloisGroup[test]; If[group==SymmetricGroup[5],NS5++]; If[group==AlternatingGroup[5],NA5++]; If[group==MetacyclicGroup[20],NF20++]; If[group==DihedralGroup[10],ND5++]; If[group==CyclicGroup[5],NC5++],Nreducible++],{r,-10,+10},{s,-10,+10},{t,-10,+10}]]; $\endgroup$ – Lorenz H Menke Nov 13 '15 at 23:46
  • $\begingroup$ In the sample code IrreduciblePolynomialQ returns true if the polynomial is reducible and QuinticGaloisGroup return the quintic Galois group of the polynomial. Then I count the cases of the five possible groups. This is an example of generic polynomials. $\endgroup$ – Lorenz H Menke Nov 13 '15 at 23:48
  • $\begingroup$ This example takes about 20 seconds to run. Set the do loop parameters to 100 or more then calculation times is hours and days. $\endgroup$ – Lorenz H Menke Nov 13 '15 at 23:49
  • $\begingroup$ @LorenzHMenke Please update your question with your code, don't put it as a comment. $\endgroup$ – C. E. Nov 14 '15 at 0:00
1
$\begingroup$

Update: It might be more convenient to use Association instead of lists of rules, if you have V10.

Instead of trying to tally the result from within the kernels, return a data structure indicating what should be incremented. Then total the results after the parallel computations have been completed.

Since you did not supply complete code, I made up a simple QuinticGaloisGroup function for proof of concept.

Clear[NS5, NA5, NF20, ND5, NC5, Nreducible, Nirreducible];
groups = {NS5, NA5, NF20, ND5, NC5, Nreducible, Nirreducible};
QuinticGaloisGroup[t_] := {SymmetricGroup[5],
    AlternatingGroup[5],
    MetacyclicGroup[20],
    DihedralGroup[10],
    CyclicGroup[5]}[[Mod[Hash[{r, s, t}], 5, 1]]];
res = ParallelTable[
   With[{test = x^5 + r x^3 + s x^2 + t (x + 1)},
    If[IrreduciblePolynomialQ[test],
     Association@                      (* remove this line, if version is below V10 *)
      Join[{Nirreducible -> 1},
       Switch[QuinticGaloisGroup[test],
        SymmetricGroup[5], {NS5 -> 1},
        AlternatingGroup[5], {NA5 -> 1},
        MetacyclicGroup[20], {NF20 -> 1},
        DihedralGroup[10], {ND5 -> 1},
        CyclicGroup[5], {NC5 -> 1},
        _, {}]
       ],
      {Nreducible -> 1}]
     ],
   {r, -10, 10}, {s, -10, 10}, {t, -10, 10}];

Then tally the results:

Merge[Flatten[res], Total]
(*
  <|Nirreducible -> 7971, NC5 -> 1633, NS5 -> 1633, NF20 -> 1524, 
    ND5 -> 1593, NA5 -> 1588, Nreducible -> 1290|>
*)

If not using Association:

Thread[groups -> Total[groups /. Flatten[res, 2] /. Thread[groups -> 0]]]
(*
  {NS5 -> 1633, NA5 -> 1588, NF20 -> 1524, ND5 -> 1593, NC5 -> 1633,
   Nreducible -> 1290, Nirreducible -> 7971}
*)
| improve this answer | |
$\endgroup$
0
$\begingroup$

Use SetSharedVariable[Ncases], but be aware that this is essentially a mutex that the master kernel must synchronize access to. This probably isn't a problem if the rest of the code in your loop is slow.

Edit A potential better solution is to do something like this after your ParallelDo has finished:

Total /@ Transpose@ParallelEvaluate[{Ncases, NS5, NA5, NF20, ND5, NC5, Nreducible, Nirreducible}]

... which will sum each kernel's local values for the iterators.

| improve this answer | |
$\endgroup$
  • $\begingroup$ The QuinticGaloisGroup function is slow. $\endgroup$ – Lorenz H Menke Nov 14 '15 at 1:41
  • $\begingroup$ As long as Ncases isn't being read/written frequently, it's a safe approach. Try it! $\endgroup$ – ZachB Nov 14 '15 at 1:42
  • $\begingroup$ I tried setting the SetSharedVariable[severl counters] and the results were slower by a factor of 10. Now the primary function QuinticGaloisGroup evaluates at hundreds to thousands of times per second depending on the test function being evaluated. Is this a potential cause of this longer total time taken? $\endgroup$ – Lorenz H Menke Nov 16 '15 at 21:52
  • $\begingroup$ I'm not following -- QuinticGaloisGroup evaluates more times now than before, thus slowing down total time? See also a new idea in my edited answer. $\endgroup$ – ZachB Nov 16 '15 at 22:22

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