#|
I Try to use futures for parallelization. I have 12 processors.
The task manager (Windows) tells me that only one processor is used.
Question: why aren't the futures run parallely?
I Run from the definitions window of DrRacket.
Here is a stripped snippet of my code. Sorry, can't strip further.
The time is in procedure posi. When I strip it away, execution times are 0 ms.
|#
;; Action compute short.
;; h : nr of disks
;; m : move number
;; f : starting peg
;; t : destination peg
;; Compute without recursion for move m of
;; the shortest path of moving all disks from peg f to peg t:
;; Which disk is moved.
;; From which peg.
;; To which peg.
;; Distribution of the disk among the pegs after the move.
#lang racket
(define (distribute n m)
(cond
((<= n m) (make-list n 1))
(else
(define-values (p q) (quotient/remainder n m))
(append (make-list (- m q) p) (make-list q (add1 p))))))
(define (ranges n)
(define d (distribute n (processor-count)))
(for/fold ((i 1) (r '()) #:result (reverse r)) ((k (in-list d)))
(values (+ i k) (cons (list (sub1 i) (+ i k -1)) r))))
(define-syntax (posi// stx)
(syntax-case stx ()
((_ m h f t posi)
#'(let ()
(define futures
(for/list ((r (in-list (ranges h))))
(future
(λ ()
(for/list ((d (in-range (car r) (cadr r))))
(posi m h d f t))))))
(apply append (map touch futures))))))
;========================================================================
(define (compute-short h m f t)
(define (exp2 n) (expt 2 n))
(define (mod2 n) (modulo n 2))
(define (mod3 n) (modulo n 3))
(define (pari n) (add1 (mod2 (add1 n))))
(define (rotd h d f t) (mod3 (* (- t f) (pari (- h d)))))
(define (rotr h f t) (rotd h 0 t f))
(define (mcnt m d) (quotient (+ m (exp2 d)) (exp2 (add1 d))))
(define (thrd m h f t) (mod3 (+ f (* m (rotr h f t)))))
(define (onto m h f t) (mod3 (- (thrd m h f t) (rotd h (disk m) f t))))
(define (from m h f t) (mod3 (+ (thrd m h f t) (rotd h (disk m) f t))))
(define (posi m h d f t) (mod3 (+ f (* (rotd h d f t) (mcnt m d)))))
(define (disk m) (sub1 (integer-length (bitwise-xor m (sub1 m)))))
(values
(disk m)
(from m h f t)
(onto m h f t)
(posi// m h f t posi)
#;(for/list ((d (in-range h))) (posi m h d f t))))
(define (test h)
(call-with-values
(λ () (compute-short h (sub1 (expt 2 h)) 0 1))
(λ (d f t distr) (writeln (list d f t (length distr) (apply = 1 distr))))))
(writeln (processor-count)); For my computer 12.
(for ((h (in-range 100000 500001 100000)))
(time (test h)))
;; Output:
;; 12
;; (0 2 1 100000 #t)
;; cpu time: 7500 real time: 7325 gc time: 1609
;; (0 2 1 200000 #t)
;; cpu time: 30390 real time: 29617 gc time: 6750
;; (0 2 1 300000 #t)
;; cpu time: 71312 real time: 69849 gc time: 16234
;; (0 2 1 400000 #t)
;; cpu time: 129890 real time: 127008 gc time: 28546
;; (0 2 1 500000 #t)
;; cpu time: 210140 real time: 206554 gc time: 46968
;; The results are correct (but take some time)
I ran my code wiih "no debugging" in the language menu.
When I run it with "debugging and profiling" enabled, (test 9999) goes well, but (test 10000) gives an error: ???
-: contract violation
expected: number?
given: #<void>