examples.scm 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. (use-modules
  2. (ice-9 futures)
  3. (ice-9 threads)
  4. (ice-9 match)
  5. ;; SRFI 19 for time related procedures
  6. (srfi srfi-19))
  7. ;; Just defining a timing macro here to conveniently measure elapsed time of
  8. ;; evaluating expressions.
  9. (define-syntax time
  10. (syntax-rules ()
  11. [(time expr expr* ...)
  12. (begin
  13. (define start-time (current-time time-monotonic))
  14. expr
  15. expr* ...
  16. (define end-time (current-time time-monotonic))
  17. (let* ([diff (time-difference end-time start-time)]
  18. [elapsed-ns (+ (/ (time-nanosecond diff) 1e9)
  19. (time-second diff))])
  20. (display (format #t "~fs~%" elapsed-ns))))]))
  21. ;; Here is a prime number which needs some calculation time: 39916801
  22. (define prime?-inefficient
  23. (lambda (num)
  24. (let loop ([divisor 2])
  25. (cond
  26. [(< divisor num)
  27. (if (= (remainder num divisor) 0)
  28. #f
  29. (loop (+ divisor 1)))]
  30. [else
  31. #t]))))
  32. ;; Define a procedure, which checks 2 numbers in parallel.
  33. (define (any-prime? num1 num2)
  34. (let ((a-future (future (prime?-inefficient num1))))
  35. ;; If the first branch of or returns false, only then the other branch is
  36. ;; evalutated, as a shortcut behavior, so the future needs to be started
  37. ;; before entering the or expression.
  38. (or (prime?-inefficient num2)
  39. (touch a-future))))
  40. (time (any-prime? 39916801 39916801))
  41. (time (prime?-inefficient 39916801))
  42. ;; Or define a parallel map procedure as shown on:
  43. ;; https://www.gnu.org/software/guile/docs/master/guile.html/Futures.html#Futures
  44. (define (par-map proc lst)
  45. (match lst
  46. (()
  47. '())
  48. ((head tail ...)
  49. (let ((tail (future (par-map proc tail)))
  50. (head (proc head)))
  51. (cons head (touch tail))))))
  52. ;; Only every <num of cores> added list element will increase runtime:
  53. (time
  54. (par-map prime?-inefficient
  55. '(39916801
  56. 39916801
  57. 39916801
  58. 39916801)))
  59. ;; Or make use of letpar to calculate let bindings in parallel:
  60. (time
  61. (letpar ([res0 (prime?-inefficient 39916801)]
  62. [res1 (prime?-inefficient 39916801)]
  63. [res2 (prime?-inefficient 39916801)]
  64. [res3 (prime?-inefficient 39916801)])
  65. (and res0 res1 res2 res3)))
  66. ;; Futures are only suitable for side effect free function calls. See:
  67. ;; https://www.gnu.org/software/guile/docs/master/guile.html/Futures.html#Futures