2
$\begingroup$

I think this is a very naive question which emerges from my poor understanding of ParallelDo and parallel computation in general.

Suppose, I have this simple code:

Do[
  
  tyuk = {{0, 0 , 0},  {0, 0, 0}, {0, 0, 0}};
  SetSharedVariable@tyuk;
  
  Do[
   tyuk[[Sequence @@ j]] = k;
   Print[tyuk];
   , {k, 2, 3, 1}];
  
  , {j, {{1, 1}, {2, 2}}}];

then I get the desired print output:

{{2,0,0},{0,0,0},{0,0,0}}

{{3,0,0},{0,0,0},{0,0,0}}

{{0,0,0},{0,2,0},{0,0,0}}

{{0,0,0},{0,3,0},{0,0,0}}

However, if I replace the inner Do with ParallelDo like this

Do[
      
      tyuk = {{0, 0 , 0},  {0, 0, 0}, {0, 0, 0}};
      SetSharedVariable@tyuk;
      
      ParallelDo[
       tyuk[[Sequence @@ j]] = k;
       Print[tyuk];
       , {k, 2, 3, 1}];
      
      , {j, {{1, 1}, {2, 2}}}];

Then the I get an wrong output,

{{3,0,0},{0,0,0},{0,0,0}}

{{3,0,0},{0,0,0},{0,0,0}}

{{0,0,0},{0,3,0},{0,0,0}}

{{0,0,0},{0,3,0},{0,0,0}}

I suspect that this is due to some issue while distributing the value of tyuk.

I would be very grateful if someone could show me the correct way to get the right output while using ParallelDo and briefly explain to me the reason why I got wrong output before.

$\endgroup$
3
  • 1
    $\begingroup$ If you want to simply want to give the definition of tyuk to the parallel kernels before calling ParallelDo, use DistributeDefinitions. The issue is that SetSharedVariable makes it so that the value of tyuk is synced between kernels, so the modifications from one look iteration can override the modifications from another. $\endgroup$
    – Lukas Lang
    Commented Jun 8, 2022 at 7:29
  • 2
    $\begingroup$ I believe the problem is that you expect ParallelDo to evaluate the expression in order when it doesn't do that. ParalleDo will return the first result, regardless of order. If your ultimate goal is to generate lists, maybe Table and ParallelTable are better suited. $\endgroup$
    – rowsi
    Commented Jun 8, 2022 at 7:29
  • 1
    $\begingroup$ See CriticalSection. $\endgroup$
    – user293787
    Commented Jun 8, 2022 at 10:01

1 Answer 1

4
$\begingroup$

I'm guessing you're seeing some sort of synchronisation issue here where the timings of the parallel loops make it so that the value of tyuk has already changed by the other loop by the time the Print is reached. Compare, for example:

Do[tyuk = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
  SetSharedVariable@tyuk;
  ParallelDo[
   Pause[k];
   tyuk[[Sequence @@ j]] = k;
   Print[tyuk];,
   {k, 2, 3, 1}];, {j, {{1, 1}, {2, 2}}}];

That said: I highly encourage you to NOT (edit: typo) write code this way. If you want to get any use out of parallel constructs like ParallelDo and ParallelTable it's honestly best you forget (for the moment at least) that SetSharedVariable even exists. I'm serious; only start using that function once you have a very good understanding of how parallelization works in WL and what trade-offs you can make. SetSharedVariable is easily one of the most over-abused functions in the language and the overhead it generates almost always destroys any gain you hope to achieve from using more kernels.

Instead, first learn how to use ParellelTable and take it from there. Or, if you have extremely simple loops you need to write, look at Compile (or FunctionCompile if you're feeling adventurous), which will almost certainly give you much better performance improvements.

$\endgroup$

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.