How can processes communicate with each other?
Message Passing
Shared Memory
Virtual Shared Memory: faking it on distributed memory machines.
When a process needs the value of a global (shared) variable or wants to set its value, it sends a request back to the scheduler. The scheduler maintains the variables, udpates their values, and sends back the requested values.
A declaration sets up the slave-side definitions and transports them to all slaves, which, therefore, need no separate init code.
![[Graphics:../Images/MSRI98_gr_95.gif]](../Images/MSRI98_gr_95.gif)
![[Graphics:../Images/MSRI98_gr_96.gif]](../Images/MSRI98_gr_96.gif)
We should have at least two remote kernels here.
![[Graphics:../Images/MSRI98_gr_97.gif]](../Images/MSRI98_gr_97.gif)
![[Graphics:../Images/MSRI98_gr_98.gif]](../Images/MSRI98_gr_98.gif)
Declare shared variables.
![[Graphics:../Images/MSRI98_gr_99.gif]](../Images/MSRI98_gr_99.gif)
Basic tests.
![[Graphics:../Images/MSRI98_gr_100.gif]](../Images/MSRI98_gr_100.gif)
![[Graphics:../Images/MSRI98_gr_101.gif]](../Images/MSRI98_gr_101.gif)
![[Graphics:../Images/MSRI98_gr_103.gif]](../Images/MSRI98_gr_103.gif)
![[Graphics:../Images/MSRI98_gr_105.gif]](../Images/MSRI98_gr_105.gif)
![[Graphics:../Images/MSRI98_gr_107.gif]](../Images/MSRI98_gr_107.gif)
Atomic update:
![[Graphics:../Images/MSRI98_gr_109.gif]](../Images/MSRI98_gr_109.gif)
![[Graphics:../Images/MSRI98_gr_111.gif]](../Images/MSRI98_gr_111.gif)
No special syntax is required to use shared variables. Just do things the normal way. If a variable is shared, all accesses are transparently sent to the master kernel.
The prototypical synchronization problem: between reading and writing a shared variable y, another process can change the value or read an obsolete value.
![[Graphics:../Images/MSRI98_gr_113.gif]](../Images/MSRI98_gr_113.gif)
A sequential execution (using Map instead of parallelMap) would ensure that the final value of y were 5. With concurrent access, it will usually be smaller.
![[Graphics:../Images/MSRI98_gr_115.gif]](../Images/MSRI98_gr_115.gif)
Exclusive access to variables can be achieved with one new primitive operation, a conditional atomic write. In machine code, it is often called test and set or read-modify-write.
![[Graphics:../Images/MSRI98_gr_117.gif]](../Images/MSRI98_gr_117.gif)
Set s to e (just like s=e), but only if s is currently unset or its value is
. Return the (old or new) value of s. The read-modify-write is atomic.
![[Graphics:../Images/MSRI98_gr_119.gif]](../Images/MSRI98_gr_119.gif)
This attempt fails:
![[Graphics:../Images/MSRI98_gr_121.gif]](../Images/MSRI98_gr_121.gif)
Release exclusive access.
![[Graphics:../Images/MSRI98_gr_123.gif]](../Images/MSRI98_gr_123.gif)
Now r2 succeees.
![[Graphics:../Images/MSRI98_gr_124.gif]](../Images/MSRI98_gr_124.gif)
Exclusive access to a variable or other resource can be controlled by a lock. Here is the typical code added to the previous example about asynchronous access to a variable.
![[Graphics:../Images/MSRI98_gr_126.gif]](../Images/MSRI98_gr_126.gif)
![[Graphics:../Images/MSRI98_gr_127.gif]](../Images/MSRI98_gr_127.gif)
![[Graphics:../Images/MSRI98_gr_128.gif]](../Images/MSRI98_gr_128.gif)
![[Graphics:../Images/MSRI98_gr_181.gif]](../Images/MSRI98_gr_181.gif)
![[Graphics:../Images/MSRI98_gr_183.gif]](../Images/MSRI98_gr_183.gif)
The classic example for access to shared resources, in this case forks placed between philosophers sitting at a round table. A philosopher needs the two forks to his left and right to eat.
The variables forks[1],...,forks[n] serve to reserve forks by conditionally setting them to a unique value.
![[Graphics:../Images/MSRI98_gr_184.gif]](../Images/MSRI98_gr_184.gif)
![[Graphics:../Images/MSRI98_gr_185.gif]](../Images/MSRI98_gr_185.gif)
Each dining philosopher is one process.
![[Graphics:../Images/MSRI98_gr_186.gif]](../Images/MSRI98_gr_186.gif)
Here's the behaviour of a philosopher: either thinking or eating.
![[Graphics:../Images/MSRI98_gr_187.gif]](../Images/MSRI98_gr_187.gif)
![[Graphics:../Images/MSRI98_gr_188.gif]](../Images/MSRI98_gr_188.gif)
We want essentially ParallelMap, but need a way to stop them cleanly.
![[Graphics:../Images/MSRI98_gr_189.gif]](../Images/MSRI98_gr_189.gif)
![[Graphics:../Images/MSRI98_gr_190.gif]](../Images/MSRI98_gr_190.gif)
After an interrupt, clean up:
![[Graphics:../Images/MSRI98_gr_191.gif]](../Images/MSRI98_gr_191.gif)
Document converted by Mathematica of Wolfram Research