Skip to main content

parallelization - ParallelTable and Precision


I'm using ParallelTable[] to calculate a function over a range of my parameters , ($\omega,\ell$). This seems to be working well (in terms of speed increase) except for some strange Precision issues.


I set the $MinPrecision=40 at the start of the notebook as well as my working precision, precision goal and accuracy goal for some computations later in the notebook as


 wp=$MinPrecision;

ac=$MinPrecision-8;
pg=wp/2;

The rest of my code basically defines some helper functions before going on to the main function (that I feed into ParallelTable). This main function uses the helper functions along with NDSolve and NIntegrate to do some computations, and it's in these that I feed the Working Precision->wp ,AccuracyGoal->ac, PrecisionGoal->pg.


I have used DistributeDefinitions on all my variables, helper functions, and the main function, and even on $MinPrecision, also all my initial conditions for NDSolve have N[...,wp] wrapped around them, but still when I use ParallelTable[...] I get errors:


 Precision::precsm. Requested precision 39.153977328439204` is smaller than $MinPrecision. 

I don't get any such error when I simply use Do[...] or Table[..] on my main function, and indeed the results differ at the 33rd decimal place, which is the decimal the above number is precision too. I have no idea what this number is unfortunately, it doesn't look like any of my outputs or inputs.


I just don't understand how this could not crop up with the non-parallelized forms, but crop up with parallelized?


Minimal Example



This is much simpler than my code, but I think it still captures it and the problem:


Definitions:


M = 1;
$MinPrecision = 40;
wp = $MinPrecision;
ac = $MinPrecision - 8;
pg = wp/2;
rinf = 15000;

The main function to be parallelized:



dGenBessE[\[Omega]_?NumericQ, l_?IntegerQ] := 
Block[{\[CapitalPhi]out, init, dinit},

init = 0.00006630728036817007679447778124486601253323 +
6.913102762021489976135937610105907096265*10^-6 I;
dinit = -6.958226432502243329110910813935678705519*10^-7 +
6.631148430876236565520382557577187147081*10^-6 I;

\[CapitalPhi]out[\[Omega], l] = \[CapitalPhi] /.
Block[{$MaxExtraPrecision = 100},

NDSolve[{\[CapitalPhi]''[r] + (2 (r - M))/(
r (r - 2 M)) \[CapitalPhi]'[
r] + ((\[Omega]^2 r^2)/(r - 2 M)^2 - (l (l + 1))/(
r (r - 2 M))) \[CapitalPhi][r] ==
0, \[CapitalPhi][rinf] ==
N[init, wp], \[CapitalPhi]'[rinf] ==
N[dinit, wp]}, \[CapitalPhi], {r, 30, 40},
WorkingPrecision -> wp, AccuracyGoal -> ac,
PrecisionGoal -> pg, MaxSteps -> \[Infinity]]][[1]];
Print["For \[Omega]=", \[Omega], " and l=", l, ": "];

Print["Kernel ID: ", $KernelID];
Print["Precision of init: ", Precision[init]];
Print["Precision of dinit: ", Precision[dinit]];
Print["\[CapitalPhi]out at 35=" ,
N[\[CapitalPhi]out[\[Omega], l][35], wp] ];
Print["Precision of \[CapitalPhi]out: ",
Precision[\[CapitalPhi]out[\[Omega], l][35]]];
]

Do Paralleization prereqs:



LaunchKernels[4]
DistributeDefinitions[M, rinf, wp, ac, pg, $MinPrecision,dGenBessE];

Attempt to run it with Paralleize for two different values:


Parallelize[{dGenBessE[1/10, 0], dGenBessE[1/10, 1]}] // AbsoluteTiming

Result


For me this leads to a


Precision::precsm: Requested precision 38.95475956978393` is smaller than   $MinPrecision. Using $MinPrecision instead.

Answer




I think your problem arises because the value of $MinPrecision is not distributed correctly (If I remember correctly none of the variables in the System context are distributed automatically).


So we have to do this by hand


ParallelEvaluate[$MinPrecision = 40]

Parallelize[{dGenBessE[1/10, 0], dGenBessE[1/10, 1]}] // AbsoluteTiming

Should now work without problems.


Also, presonally I would write the last example as


ParallelMap[dGenBessE[1/10, #]&,{0,1}] // AbsoluteTiming


or


Parallelize@Scan[dGenBessE[1/10, #] &, {0, 1}]

depending on whether you need to return values or not.


Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...

list manipulation - Selecting multiple columns from a matrix?

Sample data: data = { {{2013, 1, 1}, 24.13, 167.67, 231.82}, {{2013, 1, 2}, 32.15, 170.92, 225.99}, {{2013, 1, 3}, 35.43, 172.68, 221.67}, {{2013, 1, 4}, 36.73, 173.05, 218.32}, {{2013, 1, 5}, 58.19, 165.96, 197.05}, {{2013, 1, 6}, 69.99, 163.50, 187.52}, {{2013, 1, 7}, 71.37, 154.21, 175.58}, {{2013, 1, 8}, 72.51, 149.66, 163.25}}; I want a DateListPlot with three graphs, so for a matrix formed by columns 1 and 2, one for columns 1 and 3, and 1 for columns 1 and 4. At the moment I'm using this code: data2 = Transpose[{data[[All, 1]], data[[All, 2]]}]; data3 = Transpose[{data[[All, 1]], data[[All, 3]]}]; data4 = Transpose[{data[[All, 1]], data[[All, 4]]}]; DateListPlot[{data2, data3, data4}, Joined -> True, Filling -> {3 -> {1}}] but I have a hunch that this can be done more efficiently. I don't like the Transpose s in particular. Any ideas? edit (for extra credit) What if I need to multiply the second column by 2, which in my solution is simp...