# Using counters within parallelize [closed]

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.

• Please give skeleton example code so we can help. – David G. Stork Nov 13 '15 at 23:43
• 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}]]; – Lorenz H Menke Nov 13 '15 at 23:46
• 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. – Lorenz H Menke Nov 13 '15 at 23:48
• This example takes about 20 seconds to run. Set the do loop parameters to 100 or more then calculation times is hours and days. – Lorenz H Menke Nov 13 '15 at 23:49
• @LorenzHMenke Please update your question with your code, don't put it as a comment. – C. E. Nov 14 '15 at 0:00

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}
*)


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.

• The QuinticGaloisGroup function is slow. – Lorenz H Menke Nov 14 '15 at 1:41
• As long as Ncases isn't being read/written frequently, it's a safe approach. Try it! – ZachB Nov 14 '15 at 1:42
• 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? – Lorenz H Menke Nov 16 '15 at 21:52
• 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. – ZachB Nov 16 '15 at 22:22