What is the reason that ParallelDo works with singly-indexed iterators, but not doubly- or more-indexed iterators? For example, the code
Print[1]
ParallelDo[Pause[1], {x, 8}]
Print[2]
ParallelDo[Pause[1], {x[1], 0, 8}]
Print[3]
ParallelDo[Pause[1], {x[1][1], 0, 8}]
Print[4]
ParallelDo[Pause[1], {x[1][1][1], 0, 8}]
will run the first two cases in parallel, but will say the last two cases cannot be parallelized. Is there a way to get these latter two cases to run in parallel?
EDIT: I've edited my original post to add actual indices to the variables, where previously I had omitted them for simplicity. The behavior I'm referring to appears to be independent of what the actually indices are, and occurs in the same way even with "empty" indices. The fundamental issue is that the Do function seems to be happy to accept arbitrarily-indexed variables as iterators, while ParallelDo is unhappy with anything that has two or more sets of indices.
EDIT 2: In regard to the comments discussion with @HenrikSchumacher, it appears that the many calls to Set do cause a huge slow down. The code below demonstrates this:
sow[x_] := (foo = {foo, x};)
With[{n = 7},
Print[First@AbsoluteTiming[Reap[Do[
Sow[x[1]],
Evaluate[Sequence @@ Table[{x[i], 10}, {i, n}]]]]]];
Print[First@AbsoluteTiming[Block[{foo},
ParallelEvaluate[foo = {}];
ParallelDo[
sow[x[1]],
Evaluate[Sequence @@ Table[{x[i], 10}, {i, n}]]];
Join @@ ParallelEvaluate[Flatten@foo]]]];
Print[First@AbsoluteTiming[Block[{foo},
ParallelEvaluate[foo = {}];
ParallelDo[
Block[{x},
sow[x[1] /. Table[x[i] -> z[i], {i, n}]]
],
Evaluate[Sequence @@ Table[{z[i], 10}, {i, n}]]];
Join @@ ParallelEvaluate[Flatten@foo]]]];
Print[First@AbsoluteTiming[Block[{foo},
ParallelEvaluate[foo = {}];
ParallelDo[
Block[{x},
Do[x[i] = z[i], {i, n}];
sow[x[1]]
],
Evaluate[Sequence @@ Table[{z[i], 10}, {i, n}]]];
Join @@ ParallelEvaluate[Flatten@foo]]]];
]
The output on my machine is:
18.2045
8.19745
28.5532
34.8674
This is using the advice given here for the parallelized cases, as opposed to a ParallelSow type approach which is very slow. Note that in this code I haven't replicated the multi-index notation that originally caused this question to arise, I've just tried implementing some potential solutions for it.
The first case is using a non-parallel Do loop, and just Sowing a value at every step and Reaping them all at the end. The second case is doing the exact same thing, but with a ParallelDo, for comparison, and is a fair bit faster.
The third and fourth cases are of the forms suggested in the comments by @HenrikSchumacher to solve my problem, with the third replacing variables using /. and the fourth using Set to replace variables. Both of these solve the original problem, but are significantly slower than the ParallelDo with no replacement, and are even slower than the serial case.
x[]as an iterator. I am even surprised that Mathematica does not complain aboutx[]not being a symbol. Maybe you are looking for something likeParallelDo[Print[$KernelID -> {x, y}], {x, 0, 8}, {y, 0, 8}]? – Henrik Schumacher May 01 '18 at 06:47x[][]doesn't index anything. I am quite certain that you try to do something reasonable in the wrong way. Would you be so kind and give a simple example in code that highlights why you would like to usex[][]? – Henrik Schumacher May 01 '18 at 07:25ParallelTable[ Block[{x}, x[1][1][1] = i; $KernelID -> {x[1][1][1]} ], {i, 0, 8}]work for you? – Henrik Schumacher May 01 '18 at 07:40ParallelTable[ $KernelID -> {x[1][1][1] /. x[1][1][1] -> i}, {i, 0, 8}]but I would guess that usingSetis fast. – Henrik Schumacher May 01 '18 at 07:49