4
$\begingroup$

How can I make definitions inside ParallelTable to use them outside?

For example, if I execute:

ParallelTable[a[i] = i, {i, 1, 3}]

and after that, I try to access the value of a[1], I don't get 1 as I'd expect. Is there a way to make definitions inside ParallelTable so that I can access to them outside?

Note that what I want to do is more sophisticated than the trivial example above. Though there would probably be a way to do it without making definitions inside ParallelTable, it would really make my life easier if I could do it.

$\endgroup$
8
  • $\begingroup$ The other way around is easier: Make the definition outside the parallel construct and then distribute it over all parallel kernels. Why is this no option for you? $\endgroup$
    – halirutan
    Commented Jan 3, 2014 at 21:40
  • $\begingroup$ @halirutan Because I compute the value to assign inside the ParallelTable. $\endgroup$
    – a06e
    Commented Jan 3, 2014 at 21:42
  • $\begingroup$ The problem with this approach is that there doesn't exist one a! There are as many a's as you started subkernels and every a has a different value. If the situation is as simple as in your toy example, all a's are equal of course, but then there would be no reason to do this on the parallel kernels. Question: Which of the a's would like to be defined on your main kernel? $\endgroup$
    – halirutan
    Commented Jan 3, 2014 at 23:35
  • $\begingroup$ Consider the following small example, where the value of a indeed depends on the executed code of the sub-kernel: ParallelTable[a = i; i, {i, 1, 20}]; ParallelEvaluate[a] $\endgroup$
    – halirutan
    Commented Jan 3, 2014 at 23:36
  • 1
    $\begingroup$ You can pass it back via MathLink, possibly using the front end as an intermediary. See e.g. (14166). Or, SetSharedVariable[a]. The value of a will be held only in the master kernel and read by the slave kernels only via callbacks, so there could be some performance implications in this case. $\endgroup$ Commented Jan 4, 2014 at 0:20

2 Answers 2

5
$\begingroup$

In this case (and for any Parallel Evaluation), you have to use SetSharedFunction before use ParallelTable.

SetSharedFunction[a];
ParallelTable[a[i] = i, {i, 1, 10}];
a /@ Range[10]
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

I use a lot the SetSharedVariable too, to count operations dynamically. Here is one example:

SetSharedFunction[a];
SetSharedVariable[n];
n = 0; Dynamic@n
ParallelTable[(n++; Pause[0.5]; a[i] = i), {i, 1, 10}]

SetSharedFunction works for distributed DownValues, and SetSharedVariables to distributed OwnValues. Another common mistake is to load some Package, and try to execute one of it functions in parallel without distribute it before. SetSharedFunction solves this too.

$\endgroup$
0
$\begingroup$

Here's another way to do it that I came up with.

ClearAll[a];
Set @@@ ParallelTable[{a[i], i}, {i, 1, 10}];

Test:

In[3]:= a /@ Range[10]
Out[3]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

This seems faster than using SetSharedFunction as @Murta suggests, although SetSharedFunction is probably more general. Here's a simple test done on my computer (2 cores, 2 parallel kernels):

My method:

In[41]:= ClearAll[a];
         First@AbsoluteTiming[Set @@@ 
            ParallelTable[{a[i], BesselJ[i, 4.5]}, {i, 1, 100}]]
Out[42]= 0.043008

@Murta's method:

In[47]:= SetSharedFunction[a];
         First@AbsoluteTiming[
            ParallelTable[a[i] = BesselJ[i, 4.5], {i, 1, 100}]]
Out[48]= 0.708094
$\endgroup$
5
  • $\begingroup$ Keeping the a[i] out of the parallel kernels might be desirable. Try something like (Evaluate[Array[a, Length@#]] = #) &@ ParallelTable[BesselJ[i, 4.5], {i, 1, 100}]. $\endgroup$
    – Michael E2
    Commented Jan 5, 2014 at 16:10
  • $\begingroup$ This is not making the definitions inside the parallel kernels but rather in the master kernel, which you said initially that you didn't want. Murta's answer is a correct response to your question as written; this isn't. So, if your question is really something different, it'd be better to clarify that now. IMO you should at least show what you've tried and ruled out so far. $\endgroup$ Commented Jan 5, 2014 at 19:59
  • $\begingroup$ @OleksandrR. You're right. This doesn't answer the question as I phrased it. It does fix the problem I had, but that's irrelevant. I'm sure you understand I cannot post the detailed problem I am solving, since that would not help anyone. That's why I tried to post a simple toy case that represented my problem as closely as possible. I'll wait a couple of days in case someone else comes up with other ideas, and if there are no more answers, I'll Murta's accept answer since, as you say, it fits the question I asked better than my answer. I hope you don't mind if I don't delete my answer :) $\endgroup$
    – a06e
    Commented Jan 5, 2014 at 20:49
  • $\begingroup$ Well, this definitely isn't a bad method, so I wouldn't encourage you to delete the answer. In fact, if this suits your purposes, I doubt anyone else will be able to do much better. My point is just that the way you asked the question made it impossible for anyone else to suggest it, which strikes me as counterproductive. Also, I don't suggest that you should post your complete problem, but as you're an experienced user, implicit in the question is that you already knew of and tried this approach, MathLink-based methods, SetShared*, etc., and rejected them all. If not, you should say so. $\endgroup$ Commented Jan 5, 2014 at 21:03
  • $\begingroup$ @OleksandrR. I'm not very experienced. In fact, I did not know about SetShared*, nor had I done any MathLink-based method. $\endgroup$
    – a06e
    Commented Jan 6, 2014 at 13:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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