2

I'm trying to run long calculations, so I need to run it in parallel. I'm running two nested Do, and it works fine until I put ParallelDo instead of one of Do.

aaa = {};
Do[Do[aaa = Append[aaa, {i, j}], {j, 1, 5}], {i, 4}]
aaa

What is happening and how I can run two nested Do one of which is parallel?

  • 2
    Append is a terribly inefficient way of constructing a list. Please look into Table or Sow. – Roman Feb 01 '23 at 16:12
  • If you use AppendTo it works. Try aaa = {}; Do[Do[AppendTo[aaa, {i, j}], {j, 1, 5}], {i, 4}] and check aaa. One gets the list you want by Table easier and faster. But perhaps, your problem is more complex than described in the question. – Alexei Boulbitch Feb 01 '23 at 16:19
  • @AlexeiBoulbitch your code uses Do, not ParallelDo. – Victor K. Feb 01 '23 at 16:35
  • @Victor K. Exactly as that of OP. I guess that OP calls that "parallel do." Maybe I am wrong. – Alexei Boulbitch Feb 01 '23 at 16:44
  • OP states that his code (which works with Do) stops working with ParallelDo. Your AppendTo code is also unlikely to work with parallelization - you cannot assign to the same variable across multiple threads, without some additional tricks. – Victor K. Feb 01 '23 at 16:48

1 Answers1

3

Short answer.

Here is my answer to a different question that illustrates how you can build a list in parallel.

Long answer.

First of all, you should not use Append to incrementally build lists, as pointed out by @Roman. Lists are implemented as arrays inside Mathematica, and so Append, effectively, copies the whole array at every iteration. The following takes 3 seconds on my machine:

aaa = {}; Do[aaa = Append[aaa, i], {i, 50000}] // AbsoluteTiming

There are two useful idioms to avoid this copying: (a) create a linked list, or (b) use Sow and Reap.

bbb = {}; Do[bbb = {bbb, i}, {i, 50000}]; bbb = Flatten[bbb]; // AbsoluteTiming
(* {0.024124, Null} *)

ccc = Reap[Do[Sow[i], {i, 50000}]][[2, 1]]; // AbsoluteTiming (* {0.019154, Null} *)

aaa == bbb == ccc (* True *)

However, you cannot directly use Sow and Reap with Parallel do as described here. And the double-linked trick wouldn't work either, because the parallel kernel that executes your code needs to modify the same variable. The ParallelEvaluate in the above-linked solution solves this problem.

Victor K.
  • 5,146
  • 3
  • 21
  • 34
  • Using Append is not the problem since it will happen about 10 times only. The question was why it does not work in ParallelDo. And I could not fined the answer to this question in your Short or Long answer. – Филипп Цветков Feb 02 '23 at 10:46
  • What do you expect to happen when a statement x = x + 1 is executed in 8 threads in parallel? What will the value of x be the end of it, if it started at 0? – Victor K. Feb 02 '23 at 15:41
  • See also “Possible Issues” section in ParallelDo documentation. – Victor K. Feb 02 '23 at 15:52