enable futures by default on Mac OS X and Linux x86/x86_64; future docs to ref and guide
svn: r18396
This commit is contained in:
parent
2e0e4b8b95
commit
e71bd71035
|
@ -1,164 +0,0 @@
|
|||
#lang scribble/doc
|
||||
|
||||
@title{@bold{Futures}: Fine-grained Parallelism}
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
@(require scribble/manual
|
||||
scribble/urls
|
||||
scribble/struct
|
||||
(for-label scheme
|
||||
scheme/base
|
||||
scheme/contract
|
||||
scheme/future))
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
The PLT futures API enables the development of parallel programs which
|
||||
take advantage of machines with multiple processors, cores, or
|
||||
hardware threads.
|
||||
|
||||
@defmodule[scheme/future]{}
|
||||
|
||||
@defproc[(future [thunk (-> any)]) future?]{
|
||||
Starts running @scheme[thunk] in parallel. The @scheme[future]
|
||||
procedure returns immediately with a future descriptor value.
|
||||
}
|
||||
|
||||
@defproc[(touch [f future?]) any]{
|
||||
Returns the value computed in the future @scheme[f], blocking until
|
||||
the future completes (if it has not already completed).
|
||||
}
|
||||
|
||||
@defproc[(future? [x any/c]) boolean?]{
|
||||
Returns @scheme[#t] if @scheme[x] is a future.
|
||||
}
|
||||
|
||||
@defproc[(processor-count) exact-positive-integer?]{
|
||||
Returns the number of processors/cores/hardware threads available on
|
||||
the current system.
|
||||
}
|
||||
|
||||
@section[#:tag "besteffortpar"]{Best-Effort Parallelism}
|
||||
|
||||
The @scheme[future] API represents a best-effort attempt to execute an
|
||||
arbitrary segment of code in parallel. When designing programs and
|
||||
algorithms which leverage @scheme[future] for parallel speedup, there
|
||||
are a number of performance considerations to be aware of.
|
||||
|
||||
Futures are designed to accommodate the fact that many low-level
|
||||
functions provided by the MzScheme virtual machine are not reentrant.
|
||||
Thus, a future will execute its work in parallel until it detects an
|
||||
attempt to perform an ``unsafe'' operation (e.g. invoking a
|
||||
non-reentrant function). When such an operation is detected, the
|
||||
future will block until @scheme[touch]ed, upon which the remainder of
|
||||
its work will be done sequentially with respect to the touching
|
||||
thread (in this case, ``thread'' refers to an OS thread).
|
||||
|
||||
To guarantee that unsafe operations never execute simultaneously, only
|
||||
the initial OS thread used to start the MzScheme virtual machine (the
|
||||
``runtime thread'') is allowed to execute them. If a parallel future
|
||||
detects an attempted unsafe operation, it will signal the runtime
|
||||
thread that pending unsafe work is available, then block, waiting for
|
||||
the runtime thread to complete it. Note that as mentioned above, the
|
||||
runtime thread will not attempt to do this work until the future is
|
||||
explicitly touched. Also note that calls to @scheme[future] and
|
||||
@scheme[touch] are themselves considered unsafe operations.
|
||||
|
||||
Consider the following contrived example:
|
||||
|
||||
@schemeblock[
|
||||
(define (add-in-parallel a b)
|
||||
(let ([f (future (lambda () (+ a b)))])
|
||||
(touch f)))
|
||||
|
||||
(add-in-parallel 4 8)
|
||||
]
|
||||
|
||||
The output of this program is, as expected:
|
||||
|
||||
@verbatim|{
|
||||
12
|
||||
}|
|
||||
|
||||
Now suppose we add a print message to our function for debugging purposes:
|
||||
|
||||
@schemeblock[
|
||||
(define (add-in-parallel a b)
|
||||
(let ([f (future
|
||||
(lambda ()
|
||||
(begin
|
||||
(printf "Adding ~a and ~a together!~n" a b)
|
||||
(+ a b))))])
|
||||
(printf "About to touch my future...~n")
|
||||
(touch f)))
|
||||
|
||||
(add-in-parallel 4 8)
|
||||
]
|
||||
|
||||
Though this program still produces the same output, no work is being
|
||||
done in parallel. Because @scheme[printf] is considered an unsafe
|
||||
operation, f will block, and the print invocation (along with the
|
||||
subsequent add) will not be performed until the @scheme[touch] call.
|
||||
|
||||
@section[#:tag "logging"]{How Do I Keep Those Cores Busy?}
|
||||
|
||||
It is not always obvious when or where unsafe operations may
|
||||
be causing unacceptable performance degradation in parallel programs.
|
||||
A a general guideline, any primitive that is inlined will run in parallel.
|
||||
For example, fixnum and flonum addition do run in parallel,
|
||||
but not bignum or rational addition. Similarly, vector operations are
|
||||
generally safe, but not continuation operations. Also, allocation can run
|
||||
in parallel, as long as only a little bit of allocation happens. Once a significant
|
||||
amount of allocation happens, a parallel thread has to rendez-vous with the
|
||||
runtime thread to get new, local memory.
|
||||
|
||||
To help tell what is happening in your program, the parallel threads
|
||||
logs all of the points at which it has to synchronize
|
||||
with the runtime thread.
|
||||
For example, running the code in the previous
|
||||
example in the debug log level produces the following output:
|
||||
|
||||
@verbatim|{
|
||||
About to touch my future...
|
||||
future: 0 waiting for runtime at 1259702453747.720947: printf
|
||||
Adding 4 and 8 together!
|
||||
12
|
||||
}|
|
||||
|
||||
The message indicates which future blocked, the time it blocked and
|
||||
the primitive operation that caused it to block.
|
||||
|
||||
To be sure we are not merely seeing the effects of a race condition in
|
||||
this example, we can force the main thread to @scheme[sleep] for an
|
||||
unreasonable amount of time:
|
||||
|
||||
@schemeblock[
|
||||
(define (add-in-parallel a b)
|
||||
(let ([f (future
|
||||
(lambda ()
|
||||
(begin
|
||||
(printf "Adding ~a and ~a together!~n" a b)
|
||||
(+ a b))))])
|
||||
(sleep 10.0)
|
||||
(printf "About to touch my future...~n")
|
||||
(touch f)))
|
||||
|
||||
(add-in-parallel 4 8)
|
||||
]
|
||||
|
||||
@verbatim|{
|
||||
About to touch my future...
|
||||
future: 0 waiting for runtime at 1259702453747.720947: printf
|
||||
Adding 4 and 8 together!
|
||||
12
|
||||
}|
|
||||
|
||||
@section[#:tag "compiling"]{Enabling Futures in MzScheme Builds}
|
||||
|
||||
PLT's parallel-future support is only enabled if you pass
|
||||
@DFlag{enable-futures} to @exec{configure} when you build PLT (and
|
||||
that build currently only works with @exec{mzscheme}, not with
|
||||
@exec{mred}). When parallel-future support is not enabled,
|
||||
@scheme[future] just remembers the given thunk to call sequentially on
|
||||
a later @scheme[touch].
|
|
@ -1,3 +0,0 @@
|
|||
#lang setup/infotab
|
||||
|
||||
(define scribblings '(("futures.scrbl" ())))
|
|
@ -20,7 +20,7 @@ and memory performance of Scheme code.
|
|||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
@section{The Bytecode and Just-in-Time (JIT) Compilers}
|
||||
@section[#:tag "JIT"]{The Bytecode and Just-in-Time (JIT) Compilers}
|
||||
|
||||
Every definition or expression to be evaluated by Scheme is compiled
|
||||
to an internal bytecode format. In interactive mode, this compilation
|
||||
|
@ -264,6 +264,9 @@ the generational garbage collector (described later in
|
|||
reasonably cheap. Fixnums, in contrast are never boxed, so they are
|
||||
typically cheap to use.
|
||||
|
||||
@margin-note{See @secref["effective-futures"] for an example use of
|
||||
@tech{flonum}-specific operations.}
|
||||
|
||||
The @schememodname[scheme/flonum] library provides flonum-specific
|
||||
operations, and combinations of flonum operations allow the @tech{JIT}
|
||||
compiler to generate code that avoids boxing and unboxing intermediate
|
||||
|
@ -361,3 +364,7 @@ then the expansion of the @scheme[let] form to implement
|
|||
@scheme[m-loop] involves a closure over @scheme[n], but the compiler
|
||||
automatically converts the closure to pass itself @scheme[n] as an
|
||||
argument instead.
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
@include-section["futures.scrbl"]
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
|
||||
PLT Scheme supports multiple threads of control within a program,
|
||||
thread-local storage, some primitive synchronization mechanisms, and a
|
||||
framework for composing synchronization abstractions.
|
||||
framework for composing synchronization abstractions. In addition, the
|
||||
@scheme[scheme/future] library provides some support for parallelism
|
||||
to improve performance.
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
|
@ -14,5 +16,4 @@ framework for composing synchronization abstractions.
|
|||
@include-section["threads.scrbl"]
|
||||
@include-section["sync.scrbl"]
|
||||
@include-section["thread-local.scrbl"]
|
||||
|
||||
|
||||
@include-section["futures.scrbl"]
|
||||
|
|
|
@ -678,7 +678,8 @@ escape-continuation aborts can cross continuation barriers.
|
|||
Scheme supports multiple @deftech{threads} of evaluation. Threads run
|
||||
concurrently, in the sense that one thread can preempt another without
|
||||
its cooperation, but threads currently all run on the same processor
|
||||
(i.e., the same underlying OS process and thread).
|
||||
(i.e., the same underlying OS process and thread). See also
|
||||
@secref["futures"].
|
||||
|
||||
Threads are created explicitly by functions such as @scheme[thread].
|
||||
In terms of the evaluation model, each step in evaluation actually consists of multiple concurrent
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
@title[#:tag "threads"]{Threads}
|
||||
|
||||
See @secref["thread-model"] for basic information on the PLT Scheme
|
||||
thread model.
|
||||
thread model. See also @secref["futures"].
|
||||
|
||||
When a thread is created, it is placed into the management of the
|
||||
@tech{current custodian} and added to the current thread group (see
|
||||
|
|
38
src/configure
vendored
38
src/configure
vendored
|
@ -1349,7 +1349,7 @@ Optional Features:
|
|||
--enable-jit compile JIT support (enabled by default)
|
||||
--enable-foreign compile foreign support (enabled by default)
|
||||
--enable-places compile places support
|
||||
--enable-futures compile futures support
|
||||
--enable-futures compile futures support (usually enabled by default)
|
||||
--enable-cgcdefault use CGC (Boehm or Senora) as default build
|
||||
--enable-sgc use Senora GC instead of the Boehm GC
|
||||
--enable-sgcdebug use Senora GC for debugging
|
||||
|
@ -5865,6 +5865,7 @@ case $OS in
|
|||
case `$UNAME -m` in
|
||||
#Required for CentOS 4.6
|
||||
x86_64)
|
||||
enable_futures_by_default=yes
|
||||
CGC_X86_64="1"
|
||||
if test -d /usr/X11R6/lib64 ; then
|
||||
X_LIBS="$X_LIBS -L/usr/X11R6/lib64"
|
||||
|
@ -5878,6 +5879,9 @@ case $OS in
|
|||
alpha)
|
||||
EXTRA_GMP_OBJ="gmp_alpha_gcc.o"
|
||||
;;
|
||||
i386,i486,i586,i686)
|
||||
enable_futures_by_default=yes
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
@ -5931,6 +5935,8 @@ case $OS in
|
|||
LDFLAGS="$LDFLAGS -isysroot ${enable_sdk} -mmacosx-version-min=10.4"
|
||||
fi
|
||||
|
||||
enable_futures_by_default=yes
|
||||
|
||||
PREFLAGS="$PREFLAGS -DOS_X -D_DARWIN_UNLIMITED_SELECT"
|
||||
|
||||
STRIP_DEBUG="/usr/bin/strip -S"
|
||||
|
@ -10705,28 +10711,50 @@ fi
|
|||
if test "${enable_pthread}" = "yes" ; then
|
||||
PREFLAGS="$PREFLAGS -D_THREAD_SAFE"
|
||||
X_EXTRA_LIBS="$X_EXTRA_LIBS -pthread"
|
||||
MZOPTIONS="$MZOPTIONS -DUSE_PTHREAD_INSTEAD_OF_ITIMER"
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define USE_PTHREAD_INSTEAD_OF_ITIMER 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
############### places ###################
|
||||
|
||||
if test "${enable_places}" = "yes" ; then
|
||||
PREFLAGS="$PREFLAGS -DMZ_USE_PLACES"
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define MZ_USE_PLACES 1
|
||||
_ACEOF
|
||||
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
enable_mzrt=yes
|
||||
fi
|
||||
|
||||
############### futures ###################
|
||||
|
||||
if test "${enable_futures_by_default}" = "yes" ; then
|
||||
if test "${enable_futures}" = "" ; then
|
||||
enable_futures=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "${enable_futures}" = "yes" ; then
|
||||
PREFLAGS="$PREFLAGS -DMZ_USE_FUTURES"
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define MZ_USE_FUTURES 1
|
||||
_ACEOF
|
||||
|
||||
enable_mzrt=yes
|
||||
fi
|
||||
|
||||
############### OS threads ###################
|
||||
|
||||
if test "${enable_mzrt}" = "yes" ; then
|
||||
PREFLAGS="$PREFLAGS -DUSE_PTHREAD_INSTEAD_OF_ITIMER"
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define USE_PTHREAD_INSTEAD_OF_ITIMER 1
|
||||
_ACEOF
|
||||
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
MZRT_CGC_FLAGS="$GC_THREADS_FLAG -DTHREAD_LOCAL_ALLOC"
|
||||
LIBATOM="LIBATOM_USE"
|
||||
|
|
|
@ -44,7 +44,7 @@ AC_ARG_ENABLE(jit, [ --enable-jit compile JIT support (enabled b
|
|||
AC_ARG_ENABLE(foreign, [ --enable-foreign compile foreign support (enabled by default)], , enable_foreign=yes)
|
||||
|
||||
AC_ARG_ENABLE(places, [ --enable-places compile places support])
|
||||
AC_ARG_ENABLE(futures, [ --enable-futures compile futures support])
|
||||
AC_ARG_ENABLE(futures, [ --enable-futures compile futures support (usually enabled by default)])
|
||||
|
||||
AC_ARG_ENABLE(cgcdefault, [ --enable-cgcdefault use CGC (Boehm or Senora) as default build])
|
||||
AC_ARG_ENABLE(sgc, [ --enable-sgc use Senora GC instead of the Boehm GC])
|
||||
|
@ -575,6 +575,7 @@ case $OS in
|
|||
case `$UNAME -m` in
|
||||
#Required for CentOS 4.6
|
||||
x86_64)
|
||||
enable_futures_by_default=yes
|
||||
CGC_X86_64="1"
|
||||
if test -d /usr/X11R6/lib64 ; then
|
||||
X_LIBS="$X_LIBS -L/usr/X11R6/lib64"
|
||||
|
@ -588,6 +589,9 @@ case $OS in
|
|||
alpha)
|
||||
EXTRA_GMP_OBJ="gmp_alpha_gcc.o"
|
||||
;;
|
||||
i386,i486,i586,i686)
|
||||
enable_futures_by_default=yes
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
@ -641,6 +645,8 @@ case $OS in
|
|||
LDFLAGS="$LDFLAGS -isysroot ${enable_sdk} -mmacosx-version-min=10.4"
|
||||
fi
|
||||
|
||||
enable_futures_by_default=yes
|
||||
|
||||
PREFLAGS="$PREFLAGS -DOS_X -D_DARWIN_UNLIMITED_SELECT"
|
||||
|
||||
STRIP_DEBUG="/usr/bin/strip -S"
|
||||
|
@ -1135,28 +1141,34 @@ fi
|
|||
if test "${enable_pthread}" = "yes" ; then
|
||||
PREFLAGS="$PREFLAGS -D_THREAD_SAFE"
|
||||
X_EXTRA_LIBS="$X_EXTRA_LIBS -pthread"
|
||||
MZOPTIONS="$MZOPTIONS -DUSE_PTHREAD_INSTEAD_OF_ITIMER"
|
||||
AC_DEFINE(USE_PTHREAD_INSTEAD_OF_ITIMER, 1, [Pthread timer enabled])
|
||||
fi
|
||||
|
||||
############### places ###################
|
||||
|
||||
if test "${enable_places}" = "yes" ; then
|
||||
PREFLAGS="$PREFLAGS -DMZ_USE_PLACES"
|
||||
AC_DEFINE(MZ_USE_PLACES,1,[Places enabled])
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
enable_mzrt=yes
|
||||
fi
|
||||
|
||||
############### futures ###################
|
||||
|
||||
if test "${enable_futures_by_default}" = "yes" ; then
|
||||
if test "${enable_futures}" = "" ; then
|
||||
enable_futures=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "${enable_futures}" = "yes" ; then
|
||||
PREFLAGS="$PREFLAGS -DMZ_USE_FUTURES"
|
||||
AC_DEFINE(MZ_USE_FUTURES,1,[Futures enabled])
|
||||
enable_mzrt=yes
|
||||
fi
|
||||
|
||||
############### OS threads ###################
|
||||
|
||||
if test "${enable_mzrt}" = "yes" ; then
|
||||
PREFLAGS="$PREFLAGS -DUSE_PTHREAD_INSTEAD_OF_ITIMER"
|
||||
AC_DEFINE(USE_PTHREAD_INSTEAD_OF_ITIMER, 1, [Pthread timer enabled])
|
||||
LDFLAGS="$LDFLAGS -pthread"
|
||||
MZRT_CGC_FLAGS="$GC_THREADS_FLAG -DTHREAD_LOCAL_ALLOC"
|
||||
LIBATOM="LIBATOM_USE"
|
||||
|
|
|
@ -35,4 +35,11 @@
|
|||
/* Whether __attribute__ ((noinline)) works */
|
||||
#undef MZ_USE_NOINLINE
|
||||
|
||||
/* Enable futures and/or places: */
|
||||
#undef MZ_USE_FUTURES
|
||||
#undef MZ_USE_PLACES
|
||||
|
||||
/* Configure use of pthreads for the user-thread timer: */
|
||||
#undef USE_PTHREAD_INSTEAD_OF_ITIMER
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
consistently.)
|
||||
*/
|
||||
|
||||
#define MZSCHEME_VERSION "4.2.4.4"
|
||||
#define MZSCHEME_VERSION "4.2.4.5"
|
||||
|
||||
#define MZSCHEME_VERSION_X 4
|
||||
#define MZSCHEME_VERSION_Y 2
|
||||
#define MZSCHEME_VERSION_Z 4
|
||||
#define MZSCHEME_VERSION_W 4
|
||||
#define MZSCHEME_VERSION_W 5
|
||||
|
||||
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
|
||||
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)
|
||||
|
|
Loading…
Reference in New Issue
Block a user