I can't monitor ParallelTable:
Monitor[ParallelTable[Pause[3]; i, {i, 1, 10}], i]
just displays i
until it is finished.
Do you guys know of alternatives?
One way is to set a shared variable that would be assigned to an iterator variable, and monitor that:
SetSharedVariable[j]
Monitor[
ParallelTable[j = n;Length[FactorInteger[2^n - 1]], {n, 50, 300}],
j
]
This may make sense if the computation for each i
is rather intensive, so that the overhead of communication with the main kernel is negligible. Note also that the results you see are not generally in sequential order, since they depend on how ParallelTable
schedules the computations to available kernels. As to the original example, here is a modified version,
SetSharedVariable[j]
Monitor[ParallelTable[Pause[RandomReal[{0.5, 4.}]];j = i, {i, 1, 10}], j]
where the intervals to pause are random, so that not all kernels finish computing at the same time.
EDIT
As mentioned by @Szabolcs in the comments,
j++
in place of j=i
, if you are mostly interested in the overall progressHere is one way to find out:
j = 0;
First@AbsoluteTiming[ParallelTable[j++, {i, 1, 1000}];]/1000
which returns 0.0028
on my machine.
j
every time a value is computed. This way one could monitor how many values have already been computed out of the total. The order of computations can be just about anything, so looking at the "current value" of n
is not very informative.
$\endgroup$
j++
would probably make more sense, if one is interested in the overall progress only. As to the overhead - yes, sure, that's why I mentioned that it may make sense when the computation for each single i
is intensive.
$\endgroup$
Commented
Feb 9, 2012 at 17:01
Modifying some ideas suggested here, and a suggestions from Leonid in the comments:
SetAttributes[monitorParallelTable,HoldAll]
monitorParallelTable[expr_,iter__List,updatethreshold_]:=
Module[{counter=1,thresh=updatethreshold},
SetSharedVariable[counter];
ParallelEvaluate[localcounter=1;];
Monitor[
ParallelTable[
If[localcounter>=thresh,counter=counter+localcounter;localcounter=1,
localcounter++];expr,iter],
counter]
]
Basically, each kernel keeps a working tally of the number of elements it's solved, which dumps to a shared counter once it crosses an adjustable threshold. For example:
monitorParallelTable[Pause[RandomReal[{0.5, 4.}]]; n, {n, 5000}, 2]
Also, this should work for nested Table
, e.g.
monitorParallelTable[Pause[RandomReal[{0.5, 4.}]]; n, {n, 5000}, {m,300}, 2]
A quick check on AbsoluteTiming
shows the performance hit as a function of the threshold value:
Edit Not entirely sure why, but the counter that is monitored goes from 1 to (Maximum Iterations)/(number of kernels) rather than from 1 to (Maximum iterations)
If
statement into arbitrary parallel code).
$\endgroup$
Commented
Feb 9, 2012 at 20:05
expr
evaluates before you pass it to monitorParallelTable
, so I suspect that both your methods of pausing are equally ineffective simply because the CompoundExpression
evaluates too early and you actually pass just n
(that is, if n
did not have a global value). I think, you need some Hold*
- attribute here, perhaps HoldAll
, to make this work.
$\endgroup$
Commented
Feb 9, 2012 at 21:19
Pause
works, sometimes it's as you described. First a pause, then a rapid evaluation. Other times it seems to run on the parallel kernels. I've never really quite worked out how the Hold
business functions. Where would I put it?
$\endgroup$
Commented
Feb 9, 2012 at 21:24
SetAttributes[monitorParallelTable,HoldAll]
before your main code. As to Hold*
-attributes, search on Stack Overflow Mathematica tag, there were a couple of good threads on them there. Here is one I remember about: stackoverflow.com/questions/4856177/…
$\endgroup$
Commented
Feb 9, 2012 at 21:45
This is my final code for implementing a long calculation (demonstrated here over a plane of values) to ensure that all processors are being used and code to monitor the progress, with estimates of time remaining. The last line exports the data to a location specified in that line, so that you can easily come back to it and use it later.
(* First define your function using this format f[x_,z_], presumably \
you may have many function definitions that build off of one another, \
this is where the physics goes *)
f[x_, z_] := N[Sin[ x z]]
(* Now define the boundaries of the plane that you wish to calculate \
values over *)
xmin = 1;
xmax = 2 \[Pi];
zmin = 1;
zmax = 8;
(* Now define how many points you wish to calculate the function \
along each axis, note that the total number of calculatons will be \
xstep*ystep.
I reccomend running this prelminarily with a small number of points \
(ie 10 x 10) to determine the average time per point, so that you may \
predict how many points will take a given amout of time *)
xstep = 100;
zstep = 100;
(* You shouldn't have to touch any of the code from 1here1 to, unless \
you want to run several of these statement and are worried about the \
names of the various tables, in which case rename tab1, but don't \
forget to change the name in the export command *)
timestart = AbsoluteTime[];
counter = 0;
SetSharedVariable[counter];
PrintTemporary[Dynamic[
"Percent Completed: " <>
ToString[N[(counter*100)/((xstep + 1) (zstep + 1))]]
<> "% \nTime elapsed: " <> ToString[AbsoluteTime[] - timestart] <>
" s \nEstimated Time remaining: " <>
ToString[(((xstep + 1) (zstep + 1) - counter) (AbsoluteTime[] -
timestart))/counter]
]];
tab1 = ParallelTable[counter++;
N[f[x, z]], {x, xmin, xmax, N[Abs[xmin - xmax]/xstep]}, {z, zmin,
zmax, N[Abs[zmin - zmax]/zstep]}];
timeend = AbsoluteTime[];
Print["Total calculation time: ", timeend - timestart, " s"]
Print["Average time per data point: ", (
timeend - timestart)/((xstep + 1) (zstep + 1)), " s"]
(* 1here1 *)
(* Change the location and file name, I suggest something that is \
meaningful and you will be able to remember easily *)
Export["C:\\Users\\Ben\\Documents\\Code for group\\example.dat", tab1]
ParallelTable
might send values to process to subkernels in batches (depending on theMethod
setting), so the table iterator variable does not get values sequentially as in the case ofTable
. $\endgroup$Monitor[ParallelTable[expr, {i, 1, 10}], i]
just displaysi
until it's finished $\endgroup$ParallelTable
possibly sending batches of expressions to each kernel explains this (as I don't understand) rather than clarifying his answer... $\endgroup$