# Assignments in ParallelDo when using indexed variables

For convenience I use an indexed variables syntax to hold results of long computations for different integer parameters:

zeros[30] = longComputation[30]
zeros[40] = longComputation[40]
(* etc *)

I need to execute these computations for several values of the parameter. Since computations are completely independent, I thought that I could speed it up somewhat by evaluating these computations in parallel:

SetSharedVariable[zeros]

ParallelDo[
zeros[n] = longComputation[n],
{n, 30, 70, 10}
]

This does not work, however. I'm getting error messages like this one from each kernel:

Set::write: Tag Null in Null[30] is Protected.

and zeros[n] have weird values assigned to them:

In[171]:= zeros[30]
Out[171]= Null[30]

What's going on here and how to do what I want?

• longComputation(n) is not correct Mathematica syntax for a function call. In this case you would need SetSharedFunction as you are dealing with DownValues. However, the communication overhead you introduce with this is likely going to negate any benefits or parallelization. Try to write parallel code that never requires write access to the same variable from different threads. Reformulate your problm in terms of ParallelMap or ParallelTable. Apr 19, 2015 at 22:27
• @Szabolcs If you were writing this as an answer I don't think my answer should prevent you from posting this as such. You make very good points about performance. Apr 19, 2015 at 22:30
• Sorry, I wrote it incorrectly. Of course it should be longComputation[n] :( Apr 19, 2015 at 22:32

You have to replace SetSharedVariable with SetSharedFunction.

longComputation[n_] := n

SetSharedFunction[zeros]

ParallelDo[
zeros[n] = longComputation[n],
{n, 30, 70, 10}
]

Why? From the docs of SetSharedVariable:

Shared variables without a value evaluate to Null.

This is what was happening to you, because zeros[30] = ... defines a function (also known as a "downvalue"), not a variable. You can read more about this here. Among those types of values mentioned in that post functions correspond to downvalues and variables correspond to ownvalues.

In this case you would need SetSharedFunction as you are dealing with DownValues. However, the communication overhead you introduce with this is likely going to negate any benefits or parallelization. Try to write parallel code that never requires write access to the same variable from different threads. Reformulate your problem in terms of ParallelMap or ParallelTable.

For example, why not this?

ParallelMap[{#, longComputation[#]}&, {30, 70, 10}]
• Are you sure there would be a noticeable communication overhead? There are only five values to be evaluated, and each computation is fairly long. Apr 19, 2015 at 22:35
• @VladimirMatveev It's up to you to find out. If there isn't in this case, there might be any time you use zeros (after SetSharedFunction) in a different parallel computation. In general it is a good idea to avoid modifying the same variable from different kernels in Mathematica. If you need to assign to zeros, you can do it after you've returned a result from a parallel computation, and avoid ever setting zeros as shared. Apr 19, 2015 at 22:37
• This is a one-time computation so I think it would be fine. But anyway, thanks for the warning! Apr 19, 2015 at 22:38
• @VladimirMatveev If you like, treat it as goto . When people ask about doing such things on this site, in the majority of cases it turns out to be a bad idea. It doesn't mean that there's no room for SetSharedFunction and it's always a bad idea. Apr 19, 2015 at 22:39