![[Graphics:../Images/MSRI98_gr_44.gif]](../Images/MSRI98_gr_44.gif)
Sends the e to available links, then collects results.
We developed the basic idea in a previous example.
SetAttributes[ParallelEvaluate, HoldAll]
ParallelEvaluate[h_[exprs___]] :=h@@ Wait[List@@ Queue /@Hold[exprs] ]
This can be simplified somewhat to
ParallelEvaluate[h_[exprs___]] :=h@@ Wait[ Queue /@Unevaluated[{exprs}] ]
![[Graphics:../Images/MSRI98_gr_46.gif]](../Images/MSRI98_gr_46.gif)
Evaluates
in parallel.
We could reduce it to ParallelEvaluate,
but it's so simple to express directly:
ParallelMap[f_,h_[exprs___]] :=h@@ Wait[ Composition[Queue,f] /@ {exprs} ]
Parallelizing the outermost dimension, preserving dynamic scoping of the iterator variable
ParallelTable[e_, {i_Symbol, range__}, rest___List] := ParallelMap[Block[{i=#},Table[e, rest]]&,Range[range] ]
![[Graphics:../Images/MSRI98_gr_48.gif]](../Images/MSRI98_gr_48.gif)
![[Graphics:../Images/MSRI98_gr_50.gif]](../Images/MSRI98_gr_50.gif)
![[Graphics:../Images/MSRI98_gr_51.gif]](../Images/MSRI98_gr_51.gif)
![[Graphics:../Images/MSRI98_gr_69.gif]](../Images/MSRI98_gr_69.gif)
Move definitions of global functions and variables to the slaves:
Collect definitions (downvalues, etc.) and turn them into held programs
send them to all slaves for evaluation
![[Graphics:../Images/MSRI98_gr_70.gif]](../Images/MSRI98_gr_70.gif)
ExportEnvironment["context`"]
Mathematica code is portable: no need to have
machine-specific code on slaves!
Use existing MathLink connection to transport code: no
distribution problems, no common FS needed. Even the client code
for the toolkit itself is transported over this link.
The parameter prec gives the desired precision for the computation of the eigenvalues of a random n by n matrix.
![[Graphics:../Images/MSRI98_gr_71.gif]](../Images/MSRI98_gr_71.gif)
![[Graphics:../Images/MSRI98_gr_72.gif]](../Images/MSRI98_gr_72.gif)
tf measures the time it takes to find the eigenvalues.
![[Graphics:../Images/MSRI98_gr_73.gif]](../Images/MSRI98_gr_73.gif)
Make them known to all slaves.
![[Graphics:../Images/MSRI98_gr_74.gif]](../Images/MSRI98_gr_74.gif)
Check (we can now clear the local value of prec; it is no longer needed).
![[Graphics:../Images/MSRI98_gr_75.gif]](../Images/MSRI98_gr_75.gif)
![[Graphics:../Images/MSRI98_gr_76.gif]](../Images/MSRI98_gr_76.gif)
![[Graphics:../Images/MSRI98_gr_78.gif]](../Images/MSRI98_gr_78.gif)
Or you can perform the same computation on all slaves to measure their relative speed.
![[Graphics:../Images/MSRI98_gr_80.gif]](../Images/MSRI98_gr_80.gif)
These polynomials are conjectured to be irreducible.
![[Graphics:../Images/MSRI98_gr_82.gif]](../Images/MSRI98_gr_82.gif)
![[Graphics:../Images/MSRI98_gr_83.gif]](../Images/MSRI98_gr_83.gif)
![[Graphics:../Images/MSRI98_gr_85.gif]](../Images/MSRI98_gr_85.gif)
This computation benefits from latency hiding.
![[Graphics:../Images/MSRI98_gr_86.gif]](../Images/MSRI98_gr_86.gif)
Explicit scheduling; try to keep all processors busy, but avoid long input queues.
d=150; ids={}; While[True, While[$QueueLength󴌐, (* queue one new job *) AppendTo[ids,Queue[{d},{d,Length[FactorList[poly[d,x]]]}]]; d++ ]; If[Length[ids]>0, (* collect one result *) {res,id,ids} =WaitOne[ids]; Print[res] ]; ]
Collect orphans after an interrupt:
![[Graphics:../Images/MSRI98_gr_93.gif]](../Images/MSRI98_gr_93.gif)
Document converted by Mathematica of Wolfram Research