Revise places docs to fit the reference-manual style
This commit is contained in:
parent
af318c4501
commit
5c89df2f7f
|
@ -1,7 +1,7 @@
|
|||
#lang scribble/doc
|
||||
@(require "mz.ss")
|
||||
|
||||
@title[#:tag "concurrency" #:style 'toc]{Concurrency}
|
||||
@title[#:tag "concurrency" #:style 'toc]{Concurrency and Parallelism}
|
||||
|
||||
Racket supports multiple threads of control within a program,
|
||||
thread-local storage, some primitive synchronization mechanisms, and a
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
@(define future-eval (make-base-eval))
|
||||
@(interaction-eval #:eval future-eval (require racket/future))
|
||||
|
||||
@title[#:tag "futures"]{Futures for Parallelism}
|
||||
@title[#:tag "futures"]{Futures}
|
||||
|
||||
@guideintro["effective-futures"]{futures}
|
||||
|
||||
|
@ -19,7 +19,7 @@ Racket.}
|
|||
|
||||
The @racket[future] and @racket[touch] functions from
|
||||
@racketmodname[racket/future] provide access to parallelism as
|
||||
supported by the hardware and operation system.
|
||||
supported by the hardware and operating system.
|
||||
In contrast to @racket[thread], which provides concurrency for
|
||||
arbitrary computations without parallelism, @racket[future] provides
|
||||
parallelism for limited computations. A future executes its work in
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#lang scribble/doc
|
||||
|
||||
@title[#:tag "places"]{@bold{Places}: Coarse-grained Parallelism}
|
||||
@title[#:tag "places"]{Places}
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
|
@ -12,70 +12,53 @@
|
|||
racket/base
|
||||
racket/contract
|
||||
racket/place
|
||||
racket/flonum))
|
||||
racket/future
|
||||
racket/flonum
|
||||
racket/fixnum))
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
@deftech{Places} enable the development of parallel programs that
|
||||
take advantage of machines with multiple processors, cores, or
|
||||
hardware threads.
|
||||
@margin-note{Parallel support for @racket[place] is currently disabled by
|
||||
default. Enable places by supplying @DFlag{enable-places} to
|
||||
@exec{configure} when building Racket.}
|
||||
|
||||
@note-lib[racket/place]
|
||||
|
||||
Note: currently, parallel support for @racket[place] is disabled by
|
||||
default, and using it will raise an exception. Support can only be
|
||||
enabled if you build Racket yourself, and pass @DFlag{enable-places} to
|
||||
@exec{configure}. This works only for @exec{racket} (not
|
||||
@exec{gracket}), and it is supported only on Linux x86/x86_64, and Mac
|
||||
OS X x86/x86_64 platforms.
|
||||
@tech{Places} enable the development of parallel programs that
|
||||
take advantage of machines with multiple processors, cores, or
|
||||
hardware threads.
|
||||
|
||||
@defproc[(place [module-path module-path?] [start-proc symbol?]) place?]{
|
||||
Starts running @racket[start-proc] in parallel. @racket[start-proc] must
|
||||
be a function defined in @racket[module-path]. The @racket[place]
|
||||
procedure returns immediately with a place descriptor value representing the newly constructed place.
|
||||
Each place descriptor value is also a @racket[place-channel] that permits communication with the place.
|
||||
}
|
||||
A @deftech{place} is a parallel task that is effectively a separate
|
||||
instance of the Racket virtual machine. Places communicate through
|
||||
@deftech{place channels}, which are endpoints for a two-way buffered
|
||||
communication.
|
||||
|
||||
@defproc[(place-wait [p place?]) exact-integer?]{
|
||||
Returns the return value of a completed place @racket[p], blocking until
|
||||
the place completes (if it has not already completed).
|
||||
}
|
||||
To a first approximation, place channels allow only immutable values
|
||||
as messages over the channel: numbers, characters, booleans, immutable
|
||||
pairs, immutable vectors, and immutable structures. In addition, place
|
||||
channels themselves can be sent across channels to establish new
|
||||
(possibly more direct) lines of communication in addition to any
|
||||
existing lines. Finally, mutable values produced by
|
||||
@racket[shared-flvector], @racket[make-shared-flvector],
|
||||
@racket[shared-fxvector], @racket[make-shared-fxvector],
|
||||
@racket[shared-bytes], and @racket[make-shared-bytes] can be sent
|
||||
across place channels; mutation of such values is visible to all
|
||||
places that share the value, because they are allowed in a
|
||||
@deftech{shared memory space}.
|
||||
|
||||
@defproc[(place? [x any/c]) boolean?]{
|
||||
Returns @racket[#t] if @racket[x] is a place-descriptor value, @racket[#f] otherwise.
|
||||
}
|
||||
A @tech{place channel} can be used as a @tech{synchronizable event}
|
||||
(see @secref["sync"]) to receive a value through the channel. A place
|
||||
can also receive messages with @racket[place-channel-recv], and
|
||||
messages can be sent with @racket[place-channel-send].
|
||||
|
||||
@defproc[(place-channel) (values place-channel? place-channel?)]{
|
||||
Returns two @racket[place-channel] endpoint objects.
|
||||
|
||||
One @racket[place-channel] endpoint should be used by the current @racket[place] to send
|
||||
messages to a destination @racket[place].
|
||||
Constraints on messages across a place channel---and therefore on the
|
||||
kinds of data that places share---enable greater parallelism than
|
||||
@racket[future], even including separate @tech{garbage collection} of
|
||||
separate places. At the same time, the setup and communication costs
|
||||
for places can be higher than for futures.
|
||||
|
||||
The other @racket[place-channel] endpoint should be sent to a destination @racket[place] over
|
||||
an existing @racket[place-channel].
|
||||
}
|
||||
|
||||
@defproc[(place-channel-send [ch place-channel?] [x any/c]) void]{
|
||||
Sends an immutable message @racket[x] on channel @racket[ch].
|
||||
}
|
||||
|
||||
@defproc[(place-channel-recv [p place-channel?]) any/c]{
|
||||
Returns an immutable message received on channel @racket[ch].
|
||||
}
|
||||
|
||||
@defproc[(place-channel? [x any/c]) boolean?]{
|
||||
Returns @racket[#t] if @racket[x] is a place-channel object.
|
||||
}
|
||||
|
||||
@defproc[(place-channel-send/recv [ch place-channel?] [x any/c]) void]{
|
||||
Sends an immutable message @racket[x] on channel @racket[ch] and then
|
||||
waits for a repy message.
|
||||
Returns an immutable message received on channel @racket[ch].
|
||||
}
|
||||
|
||||
@section[#:tag "example"]{Basic Example}
|
||||
|
||||
This code launches two places, echos a message to them and then waits for the places to complete and return.
|
||||
For example, the following expression lanches two places, echoes a
|
||||
message to each, and then waits for the places to complete and return:
|
||||
|
||||
@racketblock[
|
||||
(let ([pls (for/list ([i (in-range 2)])
|
||||
|
@ -87,48 +70,75 @@ This code launches two places, echos a message to them and then waits for the pl
|
|||
(map place-wait pls))
|
||||
]
|
||||
|
||||
This is the code for the place-worker.ss module that each place will execute.
|
||||
The @filepath{place-worker.rkt} module must export the
|
||||
@racket[place-main] function that each place executes, where
|
||||
@racket[place-main] must accept a single @tech{place channel}
|
||||
argument:
|
||||
|
||||
@racketblock[
|
||||
(module place-worker racket
|
||||
(provide place-main)
|
||||
@racketmod[
|
||||
racket
|
||||
(provide place-main)
|
||||
|
||||
(define (place-main ch)
|
||||
(place-channel-send ch (format "Hello from place ~a" (place-channel-recv ch)))))
|
||||
(define (place-main ch)
|
||||
(place-channel-send ch (format "Hello from place ~a"
|
||||
(place-channel-recv ch))))
|
||||
]
|
||||
|
||||
@section[#:tag "place-channels"]{Place Channels}
|
||||
Place channels can be used with @racket[place-channel-recv], or as a
|
||||
@tech[#:doc '(lib "scribblings/reference/reference.scrbl")]{synchronizable event}
|
||||
(see @secref[#:doc '(lib "scribblings/reference/reference.scrbl") "sync"]) to receive a value
|
||||
through the channel. The channel can be used with @racket[place-channel-send]
|
||||
to send a value through the channel.
|
||||
|
||||
@section[#:tag "messagepassingparallelism"]{Message Passing Parallelism}
|
||||
@defproc[(place? [x any/c]) boolean?]{
|
||||
Returns @racket[#t] if @racket[x] is a @deftech{place descriptor}
|
||||
value, @racket[#f] otherwise. Every @tech{place descriptor}
|
||||
is also a @tech{place channel}.
|
||||
}
|
||||
|
||||
Places communicate by passing messages on place-channels.
|
||||
Only atomic values, immutable pairs, vectors, and structs can be
|
||||
communicated across places channels.
|
||||
@defproc[(place-channel? [x any/c]) boolean?]{
|
||||
Returns @racket[#t] if @racket[x] is @tech{place channel},
|
||||
@racket[#f] otherwise.
|
||||
}
|
||||
|
||||
@section[#:tag "places-architecture"]{Architecture and Garbage Collection}
|
||||
@defproc[(place [module-path module-path?] [start-proc symbol?]) place?]{
|
||||
|
||||
Places enables a @deftech{shared memory space} between all places.
|
||||
References from the @tech{shared memory space} back into a places memory space.
|
||||
The invariant of allowing no backpointers is enforced by only allowing immutable
|
||||
datastructures to be deep copied into the @tech{shared memory space}.
|
||||
Creates a @tech{place} to run the procedure that is identified by
|
||||
@racket[module-path] and @racket[start-proc]. The result is a
|
||||
@tech{place descriptor} value that represents the new parallel task;
|
||||
the place descriptor is returned immediately. The place descriptor
|
||||
value is also a @tech{place channel} that permits communication with
|
||||
the place.
|
||||
|
||||
However, mutation of atomic values in
|
||||
the @tech{shared memory space} is permitted to improve performace of
|
||||
shared-memory parallel programs.
|
||||
The module indicated by @racket[module-path] must export a function
|
||||
with the name @racket[start-proc]. The function must accept a single
|
||||
argument, which is a @tech{place channel} that corresponds to the
|
||||
other end of communication for the @tech{place descriptor} returned
|
||||
by @racket[place].}
|
||||
|
||||
Special functions such as @racket[shared-flvector] and @racket[shared-bytes] allocate
|
||||
vectors of mutable atomic values into the @tech{shared memory space}.
|
||||
|
||||
Parallel mutation of these atomic values
|
||||
can possibly lead to data races, but will not cause @exec{racket} to
|
||||
crash. In practice however, parallel tasks usually write to disjoint
|
||||
partitions of a shared vector.
|
||||
@defproc[(place-wait [p place?]) exact-integer?]{
|
||||
Returns the completion value of the place indicated by @racket[p],
|
||||
blocking until the place completes if it has not already completed.
|
||||
}
|
||||
|
||||
Places are allowed to garbage collect independently of one another.
|
||||
The shared-memory collector, however, has to pause all
|
||||
places before it can collect garbage.
|
||||
|
||||
@defproc[(place-channel) (values place-channel? place-channel?)]{
|
||||
|
||||
Returns two @tech{place channels}. Data send through the first
|
||||
channel can be received through the second channel, and data send
|
||||
through the second channel can be received from the first.
|
||||
|
||||
Typically, one place channel is used by the current @tech{place} to
|
||||
send messages to a destination @tech{place}; the other place channel
|
||||
us sent to the destination @tech{place} (via an existing @tech{place
|
||||
channel}).
|
||||
}
|
||||
|
||||
@defproc[(place-channel-send [ch place-channel?] [v any/c]) void]{
|
||||
Sends a message @racket[v] on channel @racket[ch].
|
||||
}
|
||||
|
||||
@defproc[(place-channel-recv [p place-channel?]) any/c]{
|
||||
Returns a message received on channel @racket[ch].
|
||||
}
|
||||
|
||||
@defproc[(place-channel-send/recv [ch place-channel?] [v any/c]) void]{
|
||||
Sends an immutable message @racket[v] on channel @racket[ch] and then
|
||||
waits for a reply message on the same channel.
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user