Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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.

share|improve this question
    
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? –  halirutan Jan 3 at 21:40
    
@halirutan Because I compute the value to assign inside the ParallelTable. –  becko Jan 3 at 21:42
    
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? –  halirutan Jan 3 at 23:35
    
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] –  halirutan Jan 3 at 23:36
1  
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. –  Oleksandr R. Jan 4 at 0:20
show 3 more comments

2 Answers

up vote 2 down vote accepted

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.

share|improve this answer
add comment

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
share|improve this answer
    
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}]. –  Michael E2 Jan 5 at 16:10
    
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. –  Oleksandr R. Jan 5 at 19:59
    
@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 :) –  becko Jan 5 at 20:49
    
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. –  Oleksandr R. Jan 5 at 21:03
    
@OleksandrR. I'm not very experienced. In fact, I did not know about SetShared*, nor had I done any MathLink-based method. –  becko Jan 6 at 13:37
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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