# ParallelTable local variables don't update precision

I'm finding that precision of variables updated outside ParallelTable don't update inside of it the way I'd hope. Here's the minimal code that demonstrates my point:

a1 = SetPrecision[1.0, 20];
Precision[a1]
ParallelTable[
Print[Precision[a1]];
, {j, 1}];
a1 = SetPrecision[1.0, 30];
a2 = a1;
Precision /@ {a1, a2}
ParallelTable[
Print[Precision /@ {a1, a2}];
, {j, 1}];


which outputs

20.
20.
{30., 30.}
{20.,30.}


The key problem is that output lines 3 and 4 aren't the same. a1 is defined differently inside and outside ParallelTable. Why is this and how can I make sure a1 is properly updated?

For contrast, note the problem does not occur if a1 has its value updated instead of its precision:

a1 = 1.0;
a1
ParallelTable[
Print[a1];
, {j, 1}];
a1 = 2.0;
a2 = a1;
{a1, a2}
ParallelTable[
Print[{a1, a2}];
, {j, 1}];


output:

1.
1.
{2., 2.}
{2.,2.}


Some possibly related questions:

ParallelTable and Precision

-- This seems to answer a related but different question?

ParallelTable and Table do not give same result

-- I couldn't quite grasp this one to figure out if it was answering my question. A more straightforward answer would be very helpful.

• Insert SetSharedVariable[a1, a2]; after the assignment a2=a1. This will fix it. Not completely sure what's going on though... – Lukas Jun 6 '16 at 8:19
• What you are doing updates the precision on the master kernel, but not on the slave kernels. Alternatively to what @Lukas said (if you don't want to make the variables shared variables) you can also use ParallelEvaluate to update the precision. – sebhofer Jun 6 '16 at 11:30
• @sebhofer Also thought so... But why is then the precision for a2 correct on the slave? That disturbed me – Lukas Jun 6 '16 at 11:38
• @Lukas Without having checked the details, there is one obvious difference between a1 and a2: a1 already exists in the context of the slave kernels, while a2 does not. ParallelTable automatically distributes the definition of a2, but apparently does not update a1 (which seems to be reasonable behaviour to me). Again, I didn't check this in detail, just a guess. – sebhofer Jun 6 '16 at 11:46
• @sebhofer Right, that makes sense. I overlooked that only a1 existed before the first ParallelTable. I guess you're right – Lukas Jun 6 '16 at 11:48

What you are seeing can be traced back to the behavior of DistributeDefinitions which is used internally by ParallelTable. DistributeDefinitions seems to have some way to determine which of its argument should in fact be distributed [1]. If the value of a variable is unchanged, it will do nothing. Consider the following snippet, for example:

a1 = SetPrecision[1.0, 20];
DistributeDefinitions[a1]
(*{a1}*)
DistributeDefinitions[a1]
(*{}*)


The empty braces indicate that nothing was distributed. Now, a change of precision will not trigger such an update, as can be seen when evaluating

a1 = SetPrecision[2.0, 20];
DistributeDefinitions[a1]
(*{a1}*)
a1 = SetPrecision[2.0, 30];
DistributeDefinitions[a1]
(*{}*)


I can't tell you why this is the case, maybe someone else can shed light on this. As to how to work around this, we already mentioned several possible ways in the comments:

• Using shared variables (note that this of course has additional side-effects you may or may not want)

SetSharedVariable[a1]
a1 = SetPrecision[2.0, 20]

• Manually setting the precision on all kernels

ParallelEvaluate[a1 = SetPrecision[2.0, 20]]


[1] As an aside I want to mention that the documentation seems incorrect, or confusing at the least. It states: "DistributeDefinitions in effect applies ParallelEvaluate to all assignments for values and attributes with the symbols [...], including not only ownvalues but also downvalues, upvalues, and other types of values."