Add `(ice-9 futures)'.
* doc/ref/api-scheduling.texi (Threads): Add short introduction. Mention the `threads' feature. Add cross-reference to futures. (Futures): New node. * module/Makefile.am (ICE_9_SOURCES): Add `ice-9/futures.scm'. * module/ice-9/futures.scm: New file. * test-suite/Makefile.am (SCM_TESTS): Add `tests/future.test'. * test-suite/tests/future.test: New file.
This commit is contained in:
parent
fe613fe25d
commit
0d4e6ca38f
5 changed files with 360 additions and 1 deletions
|
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2009
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2009, 2010
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
* Blocking:: How to block properly in guile mode.
|
||||
* Critical Sections:: Avoiding concurrency and reentries.
|
||||
* Fluids and Dynamic States:: Thread-local variables, etc.
|
||||
* Futures:: Fine-grain parallelism.
|
||||
* Parallel Forms:: Parallel execution of forms.
|
||||
@end menu
|
||||
|
||||
|
|
@ -195,6 +196,16 @@ Execute all thunks from the marked asyncs of the list @var{list_of_a}.
|
|||
@cindex Guile threads
|
||||
@cindex POSIX threads
|
||||
|
||||
Guile supports POSIX threads, unless it was configured with
|
||||
@code{--without-threads} or the host lacks POSIX thread support. When
|
||||
thread support is available, the @code{threads} feature is provided
|
||||
(@pxref{Feature Manipulation, @code{provided?}}).
|
||||
|
||||
The procedures below manipulate Guile threads, which are wrappers around
|
||||
the system's POSIX threads. For application-level parallelism, using
|
||||
higher-level constructs, such as futures, is recommended
|
||||
(@pxref{Futures}).
|
||||
|
||||
@deffn {Scheme Procedure} all-threads
|
||||
@deffnx {C Function} scm_all_threads ()
|
||||
Return a list of all threads.
|
||||
|
|
@ -791,6 +802,92 @@ Like @code{scm_with_dynamic_state}, but call @var{func} with
|
|||
@var{data}.
|
||||
@end deftypefn
|
||||
|
||||
@node Futures
|
||||
@subsection Futures
|
||||
@cindex futures
|
||||
@cindex fine-grain parallelism
|
||||
@cindex parallelism
|
||||
|
||||
The @code{(ice-9 futures)} module provides @dfn{futures}, a construct
|
||||
for fine-grain parallelism. A future is a wrapper around an expression
|
||||
whose computation may occur in parallel with the code of the calling
|
||||
thread, and possibly in parallel with other futures. Like promises,
|
||||
futures are essentially proxies that can be queried to obtain the value
|
||||
of the enclosed expression:
|
||||
|
||||
@lisp
|
||||
(touch (future (+ 2 3)))
|
||||
@result{} 5
|
||||
@end lisp
|
||||
|
||||
However, unlike promises, the expression associated with a future may be
|
||||
evaluated on another CPU core, should one be available. This supports
|
||||
@dfn{fine-grain parallelism}, because even relatively small computations
|
||||
can be embedded in futures. Consider this sequential code:
|
||||
|
||||
@lisp
|
||||
(define (find-prime lst1 lst2)
|
||||
(or (find prime? lst1)
|
||||
(find prime? lst2)))
|
||||
@end lisp
|
||||
|
||||
The two arms of @code{or} are potentially computation-intensive. They
|
||||
are independent of one another, yet, they are evaluated sequentially
|
||||
when the first one returns @code{#f}. Using futures, one could rewrite
|
||||
it like this:
|
||||
|
||||
@lisp
|
||||
(define (find-prime lst1 lst2)
|
||||
(let ((f (future (find prime? lst2))))
|
||||
(or (find prime? lst1)
|
||||
(touch f))))
|
||||
@end lisp
|
||||
|
||||
This preserves the semantics of @code{find-prime}. On a multi-core
|
||||
machine, though, the computation of @code{(find prime? lst2)} may be
|
||||
done in parallel with that of the other @code{find} call, which can
|
||||
reduce the execution time of @code{find-prime}.
|
||||
|
||||
Guile's futures are implemented on top of POSIX threads
|
||||
(@pxref{Threads}). Internally, a fixed-size pool of threads is used to
|
||||
evaluate futures, such that offloading the evaluation of an expression
|
||||
to another thread doesn't incur thread creation costs. By default, the
|
||||
pool contains one thread per CPU core, minus one, to account for the
|
||||
main thread.
|
||||
|
||||
@deffn {Scheme Syntax} future exp
|
||||
Return a future for expression @var{exp}. This is equivalent to:
|
||||
|
||||
@lisp
|
||||
(make-future (lambda () exp))
|
||||
@end lisp
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} make-future thunk
|
||||
Return a future for @var{thunk}, a zero-argument procedure.
|
||||
|
||||
This procedure returns immediately. Execution of @var{thunk} may begin
|
||||
in parallel with the calling thread's computations, if idle CPU cores
|
||||
are available, or it may start when @code{touch} is invoked on the
|
||||
returned future.
|
||||
|
||||
If the execution of @var{thunk} throws an exception, that exception will
|
||||
be re-thrown when @code{touch} is invoked on the returned future.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} future? obj
|
||||
Return @code{#t} if @var{obj} is a future.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} touch f
|
||||
Return the result of the expression embedded in future @var{f}.
|
||||
|
||||
If the result was already computed in parallel, @code{touch} returns
|
||||
instantaneously. Otherwise, it waits for the computation to complete,
|
||||
if it already started, or initiates it.
|
||||
@end deffn
|
||||
|
||||
|
||||
@node Parallel Forms
|
||||
@subsection Parallel forms
|
||||
@cindex parallel forms
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue