diff --git a/collects/scribblings/futures/futures.scrbl b/collects/scribblings/futures/futures.scrbl deleted file mode 100644 index 4241496097..0000000000 --- a/collects/scribblings/futures/futures.scrbl +++ /dev/null @@ -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]. diff --git a/collects/scribblings/futures/info.ss b/collects/scribblings/futures/info.ss deleted file mode 100644 index 2d6205d396..0000000000 --- a/collects/scribblings/futures/info.ss +++ /dev/null @@ -1,3 +0,0 @@ -#lang setup/infotab - -(define scribblings '(("futures.scrbl" ()))) diff --git a/collects/scribblings/guide/performance.scrbl b/collects/scribblings/guide/performance.scrbl index 46ba7ec801..30866eb5a6 100644 --- a/collects/scribblings/guide/performance.scrbl +++ b/collects/scribblings/guide/performance.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"] diff --git a/collects/scribblings/reference/concurrency.scrbl b/collects/scribblings/reference/concurrency.scrbl index e0a9ca6729..cf384281ae 100644 --- a/collects/scribblings/reference/concurrency.scrbl +++ b/collects/scribblings/reference/concurrency.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"] diff --git a/collects/scribblings/reference/eval-model.scrbl b/collects/scribblings/reference/eval-model.scrbl index 2413479573..a1b77ded73 100644 --- a/collects/scribblings/reference/eval-model.scrbl +++ b/collects/scribblings/reference/eval-model.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 diff --git a/collects/scribblings/reference/threads.scrbl b/collects/scribblings/reference/threads.scrbl index 7df71d536d..00b51c959d 100644 --- a/collects/scribblings/reference/threads.scrbl +++ b/collects/scribblings/reference/threads.scrbl @@ -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 diff --git a/src/configure b/src/configure index a1adb8948b..aa72ac24f2 100755 --- a/src/configure +++ b/src/configure @@ -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" diff --git a/src/mzscheme/configure.ac b/src/mzscheme/configure.ac index b2c75c1e32..94e212752f 100644 --- a/src/mzscheme/configure.ac +++ b/src/mzscheme/configure.ac @@ -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" diff --git a/src/mzscheme/mzconfig.h.in b/src/mzscheme/mzconfig.h.in index 425fd7b2f3..77f63e7dac 100644 --- a/src/mzscheme/mzconfig.h.in +++ b/src/mzscheme/mzconfig.h.in @@ -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 diff --git a/src/mzscheme/src/schvers.h b/src/mzscheme/src/schvers.h index fc4e229579..3a65bea205 100644 --- a/src/mzscheme/src/schvers.h +++ b/src/mzscheme/src/schvers.h @@ -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)