162 lines
190 KiB
HTML
162 lines
190 KiB
HTML
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||
|
<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"/><meta name="viewport" content="width=device-width, initial-scale=0.8"/><title>20 Parallelism</title><link rel="stylesheet" type="text/css" href="../scribble.css" title="default"/><link rel="stylesheet" type="text/css" href="../racket.css" title="default"/><link rel="stylesheet" type="text/css" href="figure.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-style.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-racket.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-racket.css" title="default"/><link rel="stylesheet" type="text/css" href="../doc-site.css" title="default"/><script type="text/javascript" src="../scribble-common.js"></script><script type="text/javascript" src="figure.js"></script><script type="text/javascript" src="../manual-racket.js"></script><script type="text/javascript" src="../manual-racket.js"></script><script type="text/javascript" src="../doc-site.js"></script><script type="text/javascript" src="../local-redirect/local-redirect.js"></script><script type="text/javascript" src="../local-redirect/local-user-redirect.js"></script><!--[if IE 6]><style type="text/css">.SIEHidden { overflow: hidden; }</style><![endif]--></head><body id="doc-racket-lang-org"><div class="tocset"><div class="tocview"><div class="tocviewlist tocviewlisttopspace"><div class="tocviewtitle"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,"tocview_0");">▼</a></td><td></td><td><a href="index.html" class="tocviewlink" data-pltdoc="x">The Racket Guide</a></td></tr></table></div><div class="tocviewsublisttop" style="display: block;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right">1 </td><td><a href="intro.html" class="tocviewlink" data-pltdoc="x">Welcome to Racket</a></td></tr><tr><td align="right">2 </td><td><a href="to-scheme.html" class="tocviewlink" data-pltdoc="x">Racket Essentials</a></td></tr><tr><td align="right">3 </td><td><a href="datatypes.html" class="tocviewlink" data-pltdoc="x">Built-<wbr></wbr>In Datatypes</a></td></tr><tr><td align="right">4 </td><td><a href="scheme-forms.html" class="tocviewlink" data-pltdoc="x">Expressions and Definitions</a></td></tr><tr><td align="right">5 </td><td><a href="define-struct.html" class="tocviewlink" data-pltdoc="x">Programmer-<wbr></wbr>Defined Datatypes</a></td></tr><tr><td align="right">6 </td><td><a href="modules.html" class="tocviewlink" data-pltdoc="x">Modules</a></td></tr><tr><td align="right">7 </td><td><a href="contracts.html" class="tocviewlink" data-pltdoc="x">Contracts</a></td></tr><tr><td align="right">8 </td><td><a href="i_o.html" class="tocviewlink" data-pltdoc="x">Input and Output</a></td></tr><tr><td align="right">9 </td><td><a href="regexp.html" class="tocviewlink" data-pltdoc="x">Regular Expressions</a></td></tr><tr><td align="right">10 </td><td><a href="control.html" class="tocviewlink" data-pltdoc="x">Exceptions and Control</a></td></tr><tr><td align="right">11 </td><td><a href="for.html" class="tocviewlink" data-pltdoc="x">Iterations and Comprehensions</a></td></tr><tr><td align="right">12 </td><td><a href="match.html" class="tocviewlink" data-pltdoc="x">Pattern Matching</a></td></tr><tr><td align="right">13 </td><td><a href="classes.html" class="tocviewlink" data-pltdoc="x">Classes and Objects</a></td></tr><tr><td align="right">14 </td><td><a href="units.html" class="tocviewlink" data-pltdoc="x">Units</a></td></tr><tr><td align="right">15 </td><td><a href="reflection.html" class="tocviewlink" data-pltdoc="x">Reflection and Dynamic Evaluation</a></td></tr><tr><td align="right">16 </td><td><a href="macros.html" class="tocviewlink" data-pltdoc="x">Macros</a></td></tr><tr><td align="right">17 </td><td><a href="languages.html" class="tocviewlink" data-pltd
|
||
|
<a href="parallelism.html#%28tech._place%29" class="techoutside" data-pltdoc="x"><span class="techinside">places</span></a>. On a platform that provides multiple processors,
|
||
|
parallelism can improve the run-time performance of a program.</p><p>See also <a href="performance.html" data-pltdoc="x">Performance</a> for information on sequential
|
||
|
performance in Racket. Racket also provides threads for
|
||
|
<a href="concurrency.html#%28tech._concurrency%29" class="techoutside" data-pltdoc="x"><span class="techinside">concurrency</span></a>, but threads do not provide parallelism; see
|
||
|
<a href="concurrency.html" data-pltdoc="x">Concurrency and Synchronization</a> for more information.</p><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""effective-futures"">20.1<tt> </tt><a name="(part._effective-futures)"></a>Parallelism with Futures</h4><p>The <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/future</span></a> library provides support for
|
||
|
performance improvement through parallelism with <a name="(tech._future)"></a><span style="font-style: italic">futures</span> and the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._future%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">future</a></span>
|
||
|
and <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._touch%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">touch</a></span> functions. The level of parallelism available from
|
||
|
those constructs, however, is limited by several factors, and the
|
||
|
current implementation is best suited to numerical tasks. The caveats
|
||
|
in <a href="performance.html#%28part._.Dr.Racket-perf%29" data-pltdoc="x">Performance in DrRacket</a> also apply to futures; notably,
|
||
|
the debugging instrumentation currently defeats futures.</p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>Other functions, such as <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=threads.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._thread%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">thread</a></span>, support the
|
||
|
creation of reliably concurrent tasks. However, threads never run truly
|
||
|
in parallel, even if the hardware and operating system support
|
||
|
parallelism.</p></blockquote></blockquote></blockquote><p>As a starting example, the <span class="RktSym">any-double?</span> function below takes a
|
||
|
list of numbers and determines whether any number in the list has a
|
||
|
double that is also in the list:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">any-double?</span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=for.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._for%252For%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">for/or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">i</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=sequences.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._in-list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">in-list</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=for.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._for%252For%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">for/or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">i2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=sequences.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._in-list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">in-list</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%7E3d%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">i2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>This function runs in quadratic time, so it can take a long time (on
|
||
|
the order of a second) on large lists like <span class="RktSym">l1</span> and
|
||
|
<span class="RktSym">l2</span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">l1</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=for.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._for%252Flist%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">for/list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">i</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=sequences.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._in-range%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">in-range</a></span><span class="hspace"> </span><span class="RktVal">5000</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">l2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=for.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._for%252Flist%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">for/list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">i</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=sequences.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._in-range%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">in-range</a></span><span class="hspace"> </span><span class="RktVal">5000</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">
|
||
|
algorithm. However, on a machine that offers at least two processing
|
||
|
units, the example above can run in about half the time using
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._future%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">future</a></span> and <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._touch%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">touch</a></span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._future%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">future</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">any-double?</span><span class="hspace"> </span><span class="RktSym">l2</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=if.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._or%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">any-double?</span><span class="hspace"> </span><span class="RktSym">l1</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._touch%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">touch</a></span><span class="hspace"> </span><span class="RktSym">f</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>The future <span class="RktSym">f</span> runs <span class="RktPn">(</span><span class="RktSym">any-double?</span><span class="stt"> </span><span class="RktSym">l2</span><span class="RktPn">)</span> in parallel to
|
||
|
<span class="RktPn">(</span><span class="RktSym">any-double?</span><span class="stt"> </span><span class="RktSym">l1</span><span class="RktPn">)</span>, and the result for <span class="RktPn">(</span><span class="RktSym">any-double?</span><span class="stt"> </span><span class="RktSym">l2</span><span class="RktPn">)</span> becomes available about the same time that it is demanded by
|
||
|
<span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._touch%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">touch</a></span><span class="stt"> </span><span class="RktSym">f</span><span class="RktPn">)</span>.</p><p>Futures run in parallel as long as they can do so safely, but the
|
||
|
notion of “future safe” is inherently tied to the
|
||
|
implementation. The distinction between “future safe” and “future unsafe”
|
||
|
operations may be far from apparent at the level of a Racket program.
|
||
|
The remainder of this section works through an example to illustrate
|
||
|
this distinction and to show how to use the future visualizer
|
||
|
can help shed light on it.</p><p>Consider the following core of a Mandelbrot-set computation:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mandelbrot</span><span class="hspace"> </span><span class="RktSym">iterations</span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">y</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">ci</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._-%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252F%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">/</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">2.0</span><span class="hspace"> </span><span class="RktSym">y</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1.0</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">cr</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._-%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252F%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">/</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class
|
||
|
<span class="RktPn">(</span><span class="RktSym">mandelbrot</span><span class="stt"> </span><span class="RktVal">10000000</span><span class="stt"> </span><span class="RktVal">62</span><span class="stt"> </span><span class="RktVal">501</span><span class="stt"> </span><span class="RktVal">1000</span><span class="RktPn">)</span> each take a while to
|
||
|
produce an answer. Computing them both, of course, takes twice as
|
||
|
long:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mandelbrot</span><span class="hspace"> </span><span class="RktVal">10000000</span><span class="hspace"> </span><span class="RktVal">62</span><span class="hspace"> </span><span class="RktVal">500</span><span class="hspace"> </span><span class="RktVal">1000</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mandelbrot</span><span class="hspace"> </span><span class="RktVal">10000000</span><span class="hspace"> </span><span class="RktVal">62</span><span class="hspace"> </span><span class="RktVal">501</span><span class="hspace"> </span><span class="RktVal">1000</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>Unfortunately, attempting to run the two computations in parallel with
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._future%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">future</a></span> does not improve performance:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._future%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">future</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mandelbrot</span><span class="hspace"> </span><span class="RktVal">10000000</span><span class="hspace"> </span><span class="RktVal">62</span><span class="hspace"> </span><span class="RktVal">501</span><span class="hspace"> </span><span class="RktVal">1000</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mandelbrot</span><span class="hspace"> </span><span class="RktVal">10000000</span><span class="hspace"> </span><span class="RktVal">62</span><span class="hspace"> </span><span class="RktVal">500</span><span class="hspace"> </span><span class="RktVal">1000</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._touch%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">touch</a></span><span class="hspace"> </span><span class="RktSym">f</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>To see why, use the <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=future-visualizer&rel=index.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">future-visualizer</span></a>, like this:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._req
|
||
|
The upper-left portion of the window contains an execution timeline:</p><p><span class="RktRes"><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_2.png" alt="image" width="606" height="306"/></span></p><p>Each horizontal row represents an OS-level thread, and the colored
|
||
|
dots represent important events in the execution of the program (they are
|
||
|
color-coded to distinguish one event type from another). The upper-left blue
|
||
|
dot in the timeline represents the future’s creation. The future
|
||
|
executes for a brief period (represented by a green bar in the second line) on thread
|
||
|
1, and then pauses to allow the runtime thread to perform a future-unsafe operation.</p><p>In the Racket implementation, future-unsafe operations fall into one of two categories.
|
||
|
A <a name="(tech._blocking)"></a><span style="font-style: italic">blocking</span> operation halts the evaluation of the future, and will not allow
|
||
|
it to continue until it is touched. After the operation completes within <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._touch%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">touch</a></span>,
|
||
|
the remainder of the future’s work will be evaluated sequentially by the runtime
|
||
|
thread. A <a name="(tech._synchronized)"></a><span style="font-style: italic">synchronized</span> operation also halts the future, but the runtime thread
|
||
|
may perform the operation at any time and, once completed, the future may continue
|
||
|
running in parallel. Memory allocation and JIT compilation are two common examples
|
||
|
of synchronized operations.</p><p>In the timeline, we see an orange dot just to the right of the green bar on thread 1 –
|
||
|
this dot represents a synchronized operation (memory allocation). The first orange
|
||
|
dot on thread 0 shows that the runtime thread performed the allocation shortly after
|
||
|
the future paused. A short time later, the future halts on a blocking operation
|
||
|
(the first red dot) and must wait until the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=futures.html%23%2528def._%2528%2528lib._racket%252Ffuture..rkt%2529._touch%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">touch</a></span> for it to be evaluated
|
||
|
(slightly after the 1049ms mark).</p><p>When you move your mouse over an event, the visualizer shows you
|
||
|
detailed information about the event and draws arrows
|
||
|
connecting all of the events in the corresponding future.
|
||
|
This image shows those connections for our future.</p><p><span class="RktRes"><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_3.png" alt="image" width="606" height="306"/></span></p><p>The dotted orange line connects the first event in the future to
|
||
|
the future that created it, and the purple lines connect adjacent
|
||
|
events within the future.</p><p>The reason that we see no parallelism is that the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%7E3c%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><</a></span> and <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">*</a></span> operations
|
||
|
in the lower portion of the loop in <span class="RktSym">mandelbrot</span> involve a mixture of
|
||
|
floating-point and fixed (integer) values. Such mixtures typically trigger a slow
|
||
|
path in execution, and the general slow path will usually be blocking.</p><p>Changing constants to be floating-points numbers in <span class="RktSym">mandelbrot</span> addresses that
|
||
|
first problem:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mandelbrot</span><span class="hspace"> </span><span class="RktSym">iterations</span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">y</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">ci</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._-%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252F%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">/</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">2.0</span><span class="hspace"> </span><span class="RktSym">y</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1.0</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">cr</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._-%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252F%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">/</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">2.0</span><span class="hspace"> </span><span class="RktSym">x</s
|
||
|
parallel. Nevertheless, we still see a special type of
|
||
|
slow-path operation limiting our parallelism (orange dots):</p><p><span class="RktRes"><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_4.png" alt="image" width="606" height="206"/></span></p><p>The problem is that most every arithmetic operation in this example
|
||
|
produces an inexact number whose storage must be allocated. While some allocation
|
||
|
can safely be performed exclusively without the aid of the runtime thread, especially
|
||
|
frequent allocation requires synchronized operations which defeat any performance
|
||
|
improvement.</p><p>By using <a href="performance.html#%28tech._flonum%29" class="techoutside" data-pltdoc="x"><span class="techinside">flonum</span></a>-specific operations (see
|
||
|
<a href="performance.html#%28part._fixnums%2Bflonums%29" data-pltdoc="x">Fixnum and Flonum Optimizations</a>), we can re-write <span class="RktSym">mandelbrot</span> to use
|
||
|
much less allocation:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mandelbrot</span><span class="hspace"> </span><span class="RktSym">iterations</span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">y</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">ci</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._fl-%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">fl-</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._fl%252F%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">fl/</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252A%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">2.0</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._-%7E3efl%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-></span>fl</a></span><span class="hspace"> </span><span class="RktSym">y</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._-%7E3efl%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-></span>fl</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1.0</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">cr</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._fl-%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">fl-</a></span><span class="hspace"> </span><span class="RktP
|
||
|
in sequential mode, but avoiding allocation also allows
|
||
|
<span class="RktSym">mandelbrot</span> to run usefully faster in parallel.
|
||
|
Executing this program yields the following in the visualizer:</p><p><span class="RktRes"><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_5.png" alt="image" width="606" height="206"/></span></p><p>Notice that only one green bar is shown here because one of the
|
||
|
mandelbrot computations is not being evaluated by a future (on
|
||
|
the runtime thread).</p><p>As a general guideline, any operation that is inlined by the
|
||
|
<a href="performance.html#%28tech._jit%29" class="techoutside" data-pltdoc="x"><span class="techinside">JIT</span></a> compiler runs safely in parallel, while other operations
|
||
|
that are not inlined (including all operations if the JIT compiler is
|
||
|
disabled) are considered unsafe. The <span class="stt">raco decompile</span> tool
|
||
|
annotates operations that can be inlined by the compiler (see
|
||
|
<a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=raco&rel=decompile.html&version=8.6" class="Sq" data-pltdoc="x"><span class="stt">raco decompile</span>: Decompiling Bytecode</a>), so the
|
||
|
decompiler can be used to help predict parallel performance.</p><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""effective-places"">20.2<tt> </tt><a name="(part._effective-places)"></a>Parallelism with Places</h4><p>The <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/place</span></a> library provides support for
|
||
|
performance improvement through parallelism with the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528form._%2528%2528lib._racket%252Fplace..rkt%2529._place%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">place</a></span>
|
||
|
form. The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528form._%2528%2528lib._racket%252Fplace..rkt%2529._place%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">place</a></span> form creates a <a name="(tech._place)"></a><span style="font-style: italic">place</span>, which is
|
||
|
effectively a new Racket instance that can run in parallel to other
|
||
|
places, including the initial place. The full power of the Racket
|
||
|
language is available at each place, but places can communicate only
|
||
|
through message passing—<wbr></wbr>using the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528def._%2528%2528lib._racket%252Fplace..rkt%2529._place-channel-put%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">place-channel-put</a></span> and
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528def._%2528%2528lib._racket%252Fplace..rkt%2529._place-channel-get%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">place-channel-get</a></span> functions on a limited set of
|
||
|
values—<wbr></wbr>which helps ensure the safety and independence of parallel
|
||
|
computations.</p><p>As a starting example, the racket program below uses a <a href="parallelism.html#%28tech._place%29" class="techoutside" data-pltdoc="x"><span class="techinside">place</span></a> to
|
||
|
determine whether any number in the list has a double that is also in
|
||
|
the list:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">main</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">any-double?</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=for.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._for%252For%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">for/or</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">i</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=sequences.html%23%2528def._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._in-list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">in-list</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=for.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._for%252For%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">for/or</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">i2</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=sequences.html%
|
||
|
channel</span>. The remaining body expressions within the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528form._%2528%2528lib._racket%252Fplace..rkt%2529._place%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">place</a></span> form
|
||
|
are evaluated in a new place, and the body expressions use <span class="RktSym">ch</span>
|
||
|
to communicate with the place that spawned the new place.</p><p>In the body of the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528form._%2528%2528lib._racket%252Fplace..rkt%2529._place%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">place</a></span> form above, the new place receives a
|
||
|
list of numbers over <span class="RktSym">ch</span> and binds the list to <span class="RktSym">l</span>. It
|
||
|
then calls <span class="RktSym">any-double?</span> on the list and binds the result to
|
||
|
<span class="RktSym">l-double?</span>. The final body expression sends the
|
||
|
<span class="RktSym">l-double?</span> result back to the original place over <span class="RktSym">ch</span>.</p><p>In DrRacket, after saving and running the above program, evaluate
|
||
|
<span class="RktPn">(</span><span class="RktSym">main</span><span class="RktPn">)</span> in the interactions window to create the new
|
||
|
place. <span class="refelem"><span class="refcolumn"><span class="refcontent">When using <a href="parallelism.html#%28tech._place%29" class="techoutside" data-pltdoc="x"><span class="techinside">places</span></a> inside DrRacket, the
|
||
|
module containing place code must be saved to a file before it will
|
||
|
execute.</span></span></span> Alternatively, save the program as <span class="stt">"double.rkt"</span>
|
||
|
and run from a command line with</p><p><span class="hspace"> </span><span class="stt">racket -tm double.rkt</span></p><p>where the <span class="nobreak"><span class="stt">-t</span></span> flag tells <span class="stt">racket</span> to load the
|
||
|
<span class="stt">double.rkt</span> module, the <span class="nobreak"><span class="stt">-m</span></span> flag calls the exported
|
||
|
<span class="RktSym">main</span> function, and <span class="nobreak"><span class="stt">-tm</span></span> combines the two flags.</p><p>The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528form._%2528%2528lib._racket%252Fplace..rkt%2529._place%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">place</a></span> form has two subtle features. First, it lifts the
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528form._%2528%2528lib._racket%252Fplace..rkt%2529._place%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">place</a></span> body to an anonymous, module-level function. This
|
||
|
lifting means that any binding referenced by the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528form._%2528%2528lib._racket%252Fplace..rkt%2529._place%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">place</a></span> body
|
||
|
must be available in the module’s top level. Second, the
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528form._%2528%2528lib._racket%252Fplace..rkt%2529._place%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">place</a></span> form <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Module_Names_and_Loading.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._dynamic-require%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">dynamic-require</a></span>s the enclosing module in
|
||
|
a newly created place. As part of the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=Module_Names_and_Loading.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._dynamic-require%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">dynamic-require</a></span>, the
|
||
|
current module body is evaluated in the new place. The consequence of
|
||
|
this second feature is that <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528form._%2528%2528lib._racket%252Fplace..rkt%2529._place%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">place</a></span> should not appear immediately
|
||
|
in a module or in a function that is called in a module’s top level;
|
||
|
otherwise, invoking the module will invoke the same module in a new
|
||
|
place, and so on, triggering a cascade of place creations that will
|
||
|
soon exhaust memory.</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">main</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta"></span><span class="RktCmt">;</span><span class="hspace"> </span><span class="RktCmt">Don't</span><span class="hspace"> </span><span class="RktCmt">do</span><span class="hspace"> </span><span class="RktCmt">this!</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">p</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528form._%2528%2528lib._racket%252Fplace..rkt%2529._place%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">place</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">ch</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=places.html%23%2528def._%2528%2528lib._racket%252Fplace..rkt%2529._place-channel-get%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">place-channel-get</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">ch</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">indirect-place-invocation</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/loca
|
||
|
distributed programming.</p><p>The example below demonstrates how to launch a remote racket node instance,
|
||
|
launch remote places on the new remote node instance, and start an
|
||
|
event loop that monitors the remote node instance.</p><p>The example code can also be found in
|
||
|
<span class="stt">"racket/distributed/examples/named/master.rkt"</span>.</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/base</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._require%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">require</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">racket/place/distributed</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">racket/class</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">racket/place</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">racket/runtime-path</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"bank.rkt"</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"tuple.rkt"</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">define-runtime-path</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">bank-path</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"bank.rkt"</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">define-runtime-path</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">tuple-path</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"tuple.rkt"</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._provide%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">provide</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">main</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/
|
||
|
<span class="stt">"localhost"</span> and starts a racloud node there that listens on port
|
||
|
6344 for further instructions. The handle to the new racloud node is
|
||
|
assigned to the <span class="RktSym">remote-node</span> variable. Localhost is used so that
|
||
|
the example can be run using only a single machine. However localhost
|
||
|
can be replaced by any host with ssh publickey access and racket. The
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=distributed-places&rel=index.html%23%2528def._%2528%2528lib._racket%252Fplace%252Fdistributed..rkt%2529._supervise-place-at%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">supervise-place-at</a></span> creates a new place on the
|
||
|
<span class="RktSym">remote-node</span>. The new place will be identified in the future by
|
||
|
its name symbol <span class="RktVal">'</span><span class="RktVal">tuple-server</span>. A place descriptor is
|
||
|
expected to be returned by invoking <span class="RktSym">dynamic-place</span> with the
|
||
|
<span class="RktSym">tuple-path</span> module path and the <span class="RktVal">'</span><span class="RktVal">make-tuple-server</span>
|
||
|
symbol.</p><p>The code for the tuple-server place exists in the file
|
||
|
<span class="stt">"tuple.rkt"</span>. The <span class="stt">"tuple.rkt"</span> file contains the use of
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=distributed-places&rel=index.html%23%2528form._%2528%2528lib._racket%252Fplace%252Fdefine-remote-server..rkt%2529._define-named-remote-server%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-named-remote-server</a></span> form, which defines a RPC server
|
||
|
suitable for invocation by <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=distributed-places&rel=index.html%23%2528def._%2528%2528lib._racket%252Fplace%252Fdistributed..rkt%2529._supervise-place-at%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">supervise-place-at</a></span>.</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/base</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._require%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">require</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">racket/match</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">racket/place/define-remote-server</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=distributed-places&rel=index.html%23%2528form._%2528%2528lib._racket%252Fplace%252Fdefine-remote-server..rkt%2529._define-named-remote-server%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-named-remote-server</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">tuple-server</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">define-state</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">h</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=hashtables.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._make-hash%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">make-hash</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">define-rpc</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">set</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">k</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">v</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releas
|
||
|
list of custom expressions as its arguments. From the identifier a
|
||
|
place-thunk function is created by prepending the <span class="stt">make-</span> prefix.
|
||
|
In this case <span class="RktSym">make-tuple-server</span>. The
|
||
|
<span class="RktSym">make-tuple-server</span> identifier is the
|
||
|
<span class="RktSym">place-function-name</span> given to the
|
||
|
<span class="RktSym">supervise-named-dynamic-place-at</span> form above. The
|
||
|
<span class="RktSym">define-state</span> custom form translates into a simple
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span> form, which is closed over by the <span class="RktSym">define-rpc</span>
|
||
|
form.</p><p>The <span class="RktSym">define-rpc</span> form is expanded into two parts. The first
|
||
|
part is the client stubs that call the rpc functions. The client
|
||
|
function name is formed by concatenating the
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=distributed-places&rel=index.html%23%2528form._%2528%2528lib._racket%252Fplace%252Fdefine-remote-server..rkt%2529._define-named-remote-server%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define-named-remote-server</a></span> identifier, <span class="stt">tuple-server</span>,
|
||
|
with the RPC function name <span class="stt">set</span> to form <span class="RktSym">tuple-server-set</span>.
|
||
|
The RPC client functions take a destination argument which is a
|
||
|
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=distributed-places&rel=index.html%23%2528def._%2528%2528lib._racket%252Fplace%252Fdistributed..rkt%2529._remote-connection%7E25%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">remote-connection%</a></span> descriptor and then the RPC function
|
||
|
arguments. The RPC client function sends the RPC function name,
|
||
|
<span class="RktSym">set</span>, and the RPC arguments to the destination by calling an
|
||
|
internal function <span class="RktSym">named-place-channel-put</span>. The RPC client
|
||
|
then calls <span class="RktSym">named-place-channel-get</span> to wait for the RPC
|
||
|
response.</p><p>The second expansion part of <span class="RktSym">define-rpc</span> is the server
|
||
|
implementation of the RPC call. The server is implemented by a match
|
||
|
expression inside the <span class="RktSym">make-tuple-server</span> function. The match
|
||
|
clause for <span class="RktSym">tuple-server-set</span> matches on messages beginning
|
||
|
with the <span class="RktVal">'</span><span class="RktVal">set</span> symbol. The server executes the RPC call with
|
||
|
the communicated arguments and sends the result back to the RPC
|
||
|
client.</p><p>The <span class="RktSym">define-cast</span> form is similar to the <span class="RktSym">define-rpc</span> form
|
||
|
except there is no reply message from the server to client</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=module.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._module%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">module</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">tuple</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">racket/base</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._require%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">require</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">racket/place</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">racket/match</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">define/provide</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">tuple-server-set</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">dest</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">k</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">v</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">named-place-channel-put</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">dest</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=quote.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._quote%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">'</a></span><span class="RktSym">set</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">k</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">v</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class=
|