My Assignment and Code
As an exercise in Parallel computing I've been tasked with implementing Conway's GoL in a way such that at every iteration only a fraction of cells are updated. I'm then to run several simulations starting with the same seed, in order to study effect of non synchronous updating.
I've implemented this sequentially as follows:
Initial variables:
gridSize = 10;
updateFraction = 0.9;
sampleSize = 8;
seed = RandomInteger[{0, 1}, {gridSize, gridSize}];
Normal GoL rules, and updated rules for randomly updating a fraction of the cells:
rulestest[{neighbours_, cell_}] :=
Module[{},
Piecewise[{{1, neighbours == 3}, {0,
neighbours <= 1 || neighbours > 3}}, cell]]
rulestestrandom[{neighbours_, cell_, randomseed_}] :=
Module[{},
Piecewise[{{cell, randomseed == 0}},
Piecewise[{{1, neighbours == 3}, {0,
neighbours <= 1 || neighbours > 3}}, cell]]]
Applying the rules to the grid:
step[matrix_] :=
Map[{Total@Delete[Flatten[#], 5], #[[2, 2]]} &,
Partition[ArrayPad[matrix, 1, "Periodic"], {3, 3}, {1, 1}], {2}]
/.{p_, q_} -> rulestest[{p, q}]
steprandom[matrix_] :=
Map[Flatten@{Total@Delete[Flatten[#], 5], #[[2, 2]],
RandomChoice[{updateFraction, 1 - updateFraction} -> {1, 0},1]}&,
Partition[ArrayPad[matrix, 1, "Periodic"], {3, 3}, {1, 1}], {2}]
/. {p_, q_, r_} -> rulestestrandom[{p, q, r}]
Doing a bunch of iterations and plotting it:
controlMatrix = seed;
controlAnimateSet = {controlMatrix};
Do[controlMatrixtemp = step[controlMatrix];
AppendTo[controlAnimateSet, controlMatrixtemp];
controlMatrix = controlMatrixtemp;, {100}]
Map[Function[testMatrix[#] = seed], Range[sampleSize]];
Map[Function[testMatrixtemp[#] = {}], Range[sampleSize]];
Map[Function[testMatrixAnimateSet[#] = {testMatrix[#]}],
Range[sampleSize]];
Do[Map[(testMatrixtemp[#] = steprandom[testMatrix[#]];
AppendTo[testMatrixAnimateSet[#], testMatrixtemp[#]];
testMatrix[#] = testMatrixtemp[#];) &, Range[sampleSize]];, {100}]
Manipulate[{Table[
ArrayPlot[testMatrixAnimateSet[m][[n]], Mesh -> True,
ImageSize -> Medium], {m, 1, 8}],
ArrayPlot[controlAnimateSet[[n]], Mesh -> True,
ImageSize -> Medium]}, {n, 1, 100, 1}]
The problem
The code runs fine just like this, sequentially. However the goal is to make it run in parallel. I figured there are two things that could potentially be parallelized.
Firstly updating the grid could be done in parallel:
step[matrix_] :=
ParallelMap[{Total@Delete[Flatten[#], 5], #[[2, 2]]} &,
Partition[ArrayPad[matrix, 1, "Periodic"], {3, 3}, {1, 1}], {2}]
/.{p_, q_} -> rulestest[{p, q}]
Now this works fine, but for grid sizes up to 100x100 (Which I've been instructed to use) this is less efficient when it comes to computing time, resulting in speedups of around 0.8 on my quadcore machine.
The second option, which in my mind seems more obvious, is to parallelize the iterations on the group of test matrices. I tried to do it as follows:
Do[ParallelMap[(testMatrixtemp[#] = steprandom[testMatrix[#]];
AppendTo[testMatrixAnimateSet[#], testMatrixtemp[#]];
testMatrix[#] = testMatrixtemp[#];) &, Range[sampleSize]];, {100}]
However this doesn't work, and I don't understand why. The code runs without errors and gives a very nice speedup of around 3.0, however the testMatrixAnimateSet
never gets appended with future iterations of the grid. Is this an error in my code, or just Mathematica being quirky? Is there a way to work around this?
SetSharedFunction[testMatrixAnimateSet]
for distributingDownValues
of symboltestMatrixAnimateSet
to parallel kernels. $\endgroup$