mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-10 22:10:21 +02:00
Implement `(ice-9 threads)' high-level constructs in terms of futures.
* module/ice-9/threads.scm (parallel, par-mapper): Rewrite in terms of `future' and `touch'. * test-suite/tests/threads.test ("par-map", "par-for-each"): New test prefixes. * doc/ref/api-scheduling.texi (Parallel Forms): Add cross-ref to futures. Recommend against the `n-' variants.
This commit is contained in:
parent
6c17f7bd71
commit
c21a5ddcaf
3 changed files with 69 additions and 21 deletions
|
@ -904,6 +904,11 @@ The functions described in this section are available from
|
|||
(use-modules (ice-9 threads))
|
||||
@end example
|
||||
|
||||
They provide high-level parallel constructs. The following functions
|
||||
are implemented in terms of futures (@pxref{Futures}). Thus they are
|
||||
relatively cheap as they re-use existing threads, and portable, since
|
||||
they automatically use one thread per available CPU core.
|
||||
|
||||
@deffn syntax parallel expr1 @dots{} exprN
|
||||
Evaluate each @var{expr} expression in parallel, each in its own thread.
|
||||
Return the results as a set of @var{N} multiple values
|
||||
|
@ -935,6 +940,16 @@ These functions are like @code{map} and @code{for-each} (@pxref{List
|
|||
Mapping}), but make their @var{proc} calls in parallel.
|
||||
@end deffn
|
||||
|
||||
Unlike those above, the functions described below take a number of
|
||||
threads as an argument. This makes them inherently non-portable since
|
||||
the specified number of threads may differ from the number of available
|
||||
CPU cores as returned by @code{current-processor-count}
|
||||
(@pxref{Processes}). In addition, these functions create the specified
|
||||
number of threads when they are called and terminate them upon
|
||||
completion, which makes them quite expensive.
|
||||
|
||||
Therefore, they should be avoided.
|
||||
|
||||
@deffn {Scheme Procedure} n-par-map n proc lst1 @dots{} lstN
|
||||
@deffnx {Scheme Procedure} n-par-for-each n proc lst1 @dots{} lstN
|
||||
Call @var{proc} on the elements of the given lists, in the same way as
|
||||
|
|
|
@ -32,19 +32,20 @@
|
|||
;;; Code:
|
||||
|
||||
(define-module (ice-9 threads)
|
||||
:export (begin-thread
|
||||
parallel
|
||||
letpar
|
||||
make-thread
|
||||
with-mutex
|
||||
monitor
|
||||
#:use-module (ice-9 futures)
|
||||
#:export (begin-thread
|
||||
parallel
|
||||
letpar
|
||||
make-thread
|
||||
with-mutex
|
||||
monitor
|
||||
|
||||
par-map
|
||||
par-for-each
|
||||
n-par-map
|
||||
n-par-for-each
|
||||
n-for-each-par-map
|
||||
%thread-handler))
|
||||
par-map
|
||||
par-for-each
|
||||
n-par-map
|
||||
n-par-for-each
|
||||
n-for-each-par-map
|
||||
%thread-handler))
|
||||
|
||||
|
||||
|
||||
|
@ -62,10 +63,9 @@
|
|||
(syntax-case x ()
|
||||
((_ e0 ...)
|
||||
(with-syntax (((tmp0 ...) (generate-temporaries (syntax (e0 ...)))))
|
||||
(syntax
|
||||
(let ((tmp0 (begin-thread e0))
|
||||
...)
|
||||
(values (join-thread tmp0) ...))))))))
|
||||
#'(let ((tmp0 (future e0))
|
||||
...)
|
||||
(values (touch tmp0) ...)))))))
|
||||
|
||||
(define-syntax letpar
|
||||
(syntax-rules ()
|
||||
|
@ -99,10 +99,10 @@
|
|||
|
||||
(define (par-mapper mapper)
|
||||
(lambda (proc . arglists)
|
||||
(mapper join-thread
|
||||
(mapper touch
|
||||
(apply map
|
||||
(lambda args
|
||||
(begin-thread (apply proc args)))
|
||||
(future (apply proc args)))
|
||||
arglists))))
|
||||
|
||||
(define par-map (par-mapper map))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;;; threads.test --- Tests for Guile threading. -*- scheme -*-
|
||||
;;;;
|
||||
;;;; Copyright 2003, 2006, 2007, 2009 Free Software Foundation, Inc.
|
||||
;;;; Copyright 2003, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
|
||||
;;;;
|
||||
;;;; This library is free software; you can redistribute it and/or
|
||||
;;;; modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -17,8 +17,9 @@
|
|||
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
(define-module (test-threads)
|
||||
:use-module (ice-9 threads)
|
||||
:use-module (test-suite lib))
|
||||
#:use-module (ice-9 threads)
|
||||
#:use-module (system base compile)
|
||||
#:use-module (test-suite lib))
|
||||
|
||||
(define (asyncs-still-working?)
|
||||
(let ((a #f))
|
||||
|
@ -70,6 +71,38 @@
|
|||
(equal? y 2)
|
||||
(equal? z 3))))))
|
||||
|
||||
;;
|
||||
;; par-map
|
||||
;;
|
||||
|
||||
(with-test-prefix "par-map"
|
||||
|
||||
(pass-if "simple"
|
||||
(compile '(letrec ((fibo (lambda (n)
|
||||
(if (<= n 1)
|
||||
n
|
||||
(+ (fibo (- n 1))
|
||||
(fibo (- n 2)))))))
|
||||
(equal? (par-map fibo (iota 13))
|
||||
(map fibo (iota 13))))
|
||||
#:to 'value
|
||||
#:env (current-module))))
|
||||
|
||||
;;
|
||||
;; par-for-each
|
||||
;;
|
||||
|
||||
(with-test-prefix "par-for-each"
|
||||
|
||||
(pass-if "simple"
|
||||
(compile '(let ((v (make-vector 6 #f)))
|
||||
(par-for-each (lambda (n)
|
||||
(vector-set! v n n))
|
||||
(iota 6))
|
||||
(equal? v (list->vector (iota 6))))
|
||||
#:to 'value
|
||||
#:env (current-module))))
|
||||
|
||||
;;
|
||||
;; n-par-for-each
|
||||
;;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue