# how to parallelize nested do loops [closed]

I have four Do loops which the outer loops iterate over the inner loops. This is my code

    jjp = 0;
terms = 2;
la = Table[0, {i, 1, 8}, {j, 1, 8}];
SetSharedVariable[la, ii]
Do[Do[m = -n + (jj - 1); jp = jjp + jj; iip = 0;
Do[ParallelDo[u = -v + (ii - 1); ip = iip + ii;
Print[jp, ip, KroneckerDelta[n, v] KroneckerDelta[m, u]];
la[[jp, ip]] = KroneckerDelta[n, v] KroneckerDelta[m, u];, {ii,2v+1}];
iip = ip;, {v, terms}];, {jj, 2 n + 1}];
jjp = jp;, {n, terms}];
la // MatrixForm


with above code I will got following result

    {{0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1}}


But the result should be the following

    {{1, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 1}}


can anyone help me with this?

• Your question title doesn't match your question. Please consider re-titling. As for your actual question: without knowing what you're trying to do, we can't answer the question, because there is no context given for the correct result. Obviously we can't fix what you've done unless we know why the result should be the second list rather than the actual output from the code. – march Nov 4 '15 at 16:30
• So you're trying to make the identity matrix? Why not just do IdentityMatrix[8]? Or is this a simple example of what you're trying to do, and you're trying to figure out why the code above doesn't work so that you can apply to your more complex problem? A couple of things: (1) you don't need to nest Do loops: see the docs for Do; (2) if you tell us what you're actually trying to do, we might come up with a better way (usually, in Mathematica, you don't need loops); (3) there are lots of useful built-ins like IdentityMatrix: get cozy with docs and learn! – march Nov 4 '15 at 16:52
• Replacing ParallelDo with Do will give the expected Identity Matrix. If my understanding of the question is correct, the question is why ParallelDo doesn't give the same result that Do does. My guess is that there could be some initialization/kernel communication mixup issues. Notice that adding the line ip=3; in the loop makes both Do and ParallelDo return the expected Identity Matrix. Do[Do[m = -n + (jj - 1); jp = jjp + jj; iip = 0; ip = 3;Not quite sure though. – Lotus Nov 4 '15 at 16:55
• @Lotus. Aha! Now that makes more sense. I could not figure out what the question was (clearly from my comments). OP: please consider re-writing the text a little to make it explicit that the code works if you use Do but doesn't if you use ParallelDo. – march Nov 4 '15 at 16:58
• Try debugging with this Print variant: Print[{m, n, u, v, ii, jj, iip, jjp, ip, jp, KroneckerDelta[n, v] KroneckerDelta[m, u]}]. What you should see is that the changes to ii need not be ordered (that's the point of parallelizing) and this creates behavior differences for values that depend on ii. – Daniel Lichtblau Nov 4 '15 at 17:12

This variant seems to work.

jjp = 0;
terms = 2;
la = ConstantArray[0, {8, 8}];
Do[
Do[
m = -n + (jj - 1); jp = jjp + jj; iip = 0;
Do[
SetSharedVariable[la];
ParallelDo[
privateu = -v + (ii - 1); privateip = iip + ii;
Print[{m, n, privateu, v, ii, jj, iip, jjp, privateip, jp,
KroneckerDelta[n, v] KroneckerDelta[m, privateu]}];
la[[jp, privateip]] =
KroneckerDelta[n, v] KroneckerDelta[m, privateu],
{ii, 2 v + 1}, DistributedContexts -> "Global"];
iip = iip + 2 v + 1,
{v, terms}]
,
{jj, 2 n + 1}];
jjp = jp,
{n, terms}];
la


Salient differences: (1) Put u and ip into non-distributed contexts so there isn't "cross-talk" between kernels about their values. (2) I changed the iip update following the innermost loop to add 2v+1. This has the effect of making it behave independently of ordering of the inner loop.

• Thanks for try to improve the code. But if you change terms = 2; la = ConstantArray[0, {8, 8}]; withterms = 10; la = ConstantArray[0, {terms (terms + 2), terms (terms + 2)}]; to generate the bigger matrix I will get by AbsoluteTiming for above modified code {40.88, Null} while for my code posted above without ParallelDo I will get {0.0738672, Null}. – user35323 Nov 5 '15 at 7:33
• The slowness of ParallelDo vs Do in this example is not new. It was already manifest in your original code. You asked how to correct the parallelized code. Making it faster is a very different matter. For that you might try parallelizing the outermost loop instead of innermost. Less communication overhead that way. – Daniel Lichtblau Nov 5 '15 at 16:46
• Thanks. The idea for using ParallelDo was to make it as much as possible faster. But it seems I did it in wrong way because I am not so familiar with parallelization. This is my try but doesn't work terms = 10;ParallelEvaluate[jjp = 0]; la = ConstantArray[0, {terms (terms + 2), terms (terms + 2)}]; SetSharedVariable[la];ParallelDo[Do[m=-n+(jj-1);jp=jjp+jj; iip = 0; Do[Do[privateu=-v+(ii-1);privateip=iip+ii;la[[jp,privateip]] = KroneckerDelta[n,v] KroneckerDelta[m,privateu],{ii,2v+1}];iip=iip+2 v+1,{v,terms}],{jj,2n+1}];jjp=jjp+2n+1,{n,terms},DistributedContexts->"Global"];` – user35323 Nov 6 '15 at 10:56
• I hope someone can give better guidance on how to parallelize the outer loop to get both speed and correctness. I also lack the expertise; I had enough trouble working out the correctness issues with the previous version. – Daniel Lichtblau Nov 6 '15 at 16:13