* map-par slower than map @ 2022-10-12 17:19 Damien Mattei 2022-10-12 18:45 ` Maxime Devos 2022-10-12 21:55 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 0 siblings, 2 replies; 27+ messages in thread From: Damien Mattei @ 2022-10-12 17:19 UTC (permalink / raw) To: guile-user, guile-devel Hello, all is in the title, i test on a approximately 30000 element list , i got 9s with map and 3min 30s with par-map on exactly the same piece of code!? what i change in code is in comments: {unified-minterms-set-1 <+ (map function-unify-minterms-list minterms-set)} ;;(par-map function-unify-minterms-list minterms-set)} translated from Scheme+ to Scheme: (define unified-minterms-set-1 (map function-unify-minterms-list minterms-set)) ;;(par-map function-unify-minterms-list minterms-set)) best regards, Damien ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-12 17:19 map-par slower than map Damien Mattei @ 2022-10-12 18:45 ` Maxime Devos 2022-10-12 20:20 ` Damien Mattei 2022-10-12 21:55 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 1 sibling, 1 reply; 27+ messages in thread From: Maxime Devos @ 2022-10-12 18:45 UTC (permalink / raw) To: Damien Mattei, guile-user, guile-devel [-- Attachment #1.1.1: Type: text/plain, Size: 606 bytes --] On 12-10-2022 19:19, Damien Mattei wrote: > Hello, > all is in the title, i test on a approximately 30000 element list , i got > 9s with map and 3min 30s with par-map on exactly the same piece of code!? > > [...] > > translated from Scheme+ to Scheme: > (define unified-minterms-set-1 (map function-unify-minterms-list > minterms-set)) ;;(par-map function-unify-minterms-list minterms-set)) The definition of 'function-unify-minterms-list' and 'minterms-set' is missing. Without a test case, we can only speculate what's going on. (E.g., maybe it grabs a mutex). Greetings, Maxime. [-- Attachment #1.1.2: OpenPGP public key --] [-- Type: application/pgp-keys, Size: 929 bytes --] [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 236 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-12 18:45 ` Maxime Devos @ 2022-10-12 20:20 ` Damien Mattei 2022-10-12 20:27 ` Damien Mattei 2022-10-12 21:44 ` Maxime Devos 0 siblings, 2 replies; 27+ messages in thread From: Damien Mattei @ 2022-10-12 20:20 UTC (permalink / raw) To: Maxime Devos; +Cc: guile-user, guile-devel Mutex? i do not think code has situation where dead lock could happen, it is a code about minimalising logic expressions, it uses minterms , minterms set is a set of minterms :like this: example: ((1 1 0) (1 1 1)) will be unified : (1 1 x) because 0 and 1 are replaced by x the minterms-set could have thousands of pair (mathematic not lisp) minterms to unify if there is more than one x as result there is no need to continue so i escape with a continuation: minterms-set = { ((1 0 1 0) (1 1 1 0)) ((1 0 1 0) (1 1 0 1)) ((1 0 1 0) (1 0 1 1)) ((1 0 1 0) (0 1 1 1)) ((0 1 1 0) (1 1 1 0)) ((0 1 1 0) (1 1 0 1)) ((0 1 1 0) (1 0 1 1)) ((0 1 1 0) (0 1 1 1)) ((0 1 0 1) (1 1 1 0)) ((0 1 0 1) (1 1 0 1)) ((0 1 0 1) (1 0 1 1)) ((0 1 0 1) (0 1 1 1)) ((0 0 1 1) (1 1 1 0)) ((0 0 1 1) (1 1 0 1)) ((0 0 1 1) (1 0 1 1)) ((0 0 1 1) (0 1 1 1)) } replace { } by () to have the list, other example at another level : minterms-set = { ((0 x 1 1) (x 1 1 1)) ((0 x 1 1) (1 x 1 1)) ((0 x 1 1) (1 1 x 1)) ((0 x 1 1) (1 1 1 x)) ((x 0 1 1) (x 1 1 1)) ((x 0 1 1) (1 x 1 1)) ((x 0 1 1) (1 1 x 1)) ((x 0 1 1) (1 1 1 x)) ((0 1 x 1) (x 1 1 1)) ((0 1 x 1) (1 x 1 1)) ((0 1 x 1) (1 1 x 1)) ((0 1 x 1) (1 1 1 x)) ((x 1 0 1) (x 1 1 1)) ((x 1 0 1) (1 x 1 1)) ((x 1 0 1) (1 1 x 1)) ((x 1 0 1) (1 1 1 x)) ((0 1 1 x) (x 1 1 1)) ((0 1 1 x) (1 x 1 1)) ((0 1 1 x) (1 1 x 1)) ((0 1 1 x) (1 1 1 x)) ((x 1 1 0) (x 1 1 1)) ((x 1 1 0) (1 x 1 1)) ((x 1 1 0) (1 1 x 1)) ((x 1 1 0) (1 1 1 x)) ((1 0 1 x) (x 1 1 1)) ((1 0 1 x) (1 x 1 1)) ((1 0 1 x) (1 1 x 1)) ((1 0 1 x) (1 1 1 x)) ((1 x 1 0) (x 1 1 1)) ((1 x 1 0) (1 x 1 1)) ((1 x 1 0) (1 1 x 1)) ((1 x 1 0) (1 1 1 x)) } here we see some minterms are already unified it is not easy to read even by me because i wrote the code many years ago and is split in many files, but here it is: (par-map function-unify-minterms-list minterms-set) {function-unify-minterms-list <+ (λ (L) (apply function-unify-two-minterms-and-tag L))} (define (unify-two-minterms mt1 mt2) (function-map-with-escaping-by-kontinuation2 (macro-function-compare-2-bits-with-continuation) mt1 mt2)) ;; (function-map-with-escaping-by-kontinuation2 (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 0) '(1 1 0 1 1 1 1 1)) ;; list1 = (1 1 0 1 0 1 1 0) ;; more-lists = ((1 1 0 1 1 1 1 1)) ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 1)) ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> ;; #f ;; ;; (function-map-with-escaping-by-kontinuation2 (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 0) '(1 1 0 1 1 1 1 0)) ;; list1 = (1 1 0 1 0 1 1 0) ;; more-lists = ((1 1 0 1 1 1 1 0)) ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 0)) ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> ;; '(1 1 0 1 x 1 1 0) (define (function-map-with-escaping-by-kontinuation2 clozure list1 . more-lists) (call/cc (lambda (kontinuation) (let ((lists (cons list1 more-lists)) (funct-continu ;; this function have the kontinuation in his environment (lambda (arg1 . more-args) (let ((args (cons arg1 more-args))) (apply clozure kontinuation args))))) ;; a tester: (apply clozure (cons conti args)) ;; (newline) ;; (dv list1) ;; (dv more-lists) ;; (dv lists) ;; (dv clozure) ;; (newline) (apply map funct-continu lists))))) (define-syntax macro-function-compare-2-bits-with-continuation ;; continuation version of macro-compare-2-bits ;; i need a macro because of external function to the clozure (syntax-rules () ((_) (let ((cnt 0)) ;; counter (lambda (continuation b1 b2) (if (equal? b1 b2) b1 (begin (set! cnt (add1 cnt)) ;; we leave with continuation in case cpt > 1, we can have used a flag too instead of a counter (when (> cnt 1) (continuation #f)) ;; escaping with the continuation 'x))))))) ;; return x in case of (b1,b2) = (O,1) or (1,0) what could have caused mutex if in the latter definition above (let ((cnt 0)) ;; counter was defined at top level and shared by all threads!!! yes there could have be some mutex but this is not the case, i think even all function are pure so why is it more slow with // than without? Damien On Wed, Oct 12, 2022 at 8:45 PM Maxime Devos <maximedevos@telenet.be> wrote: > On 12-10-2022 19:19, Damien Mattei wrote: > > Hello, > > all is in the title, i test on a approximately 30000 element list , i got > > 9s with map and 3min 30s with par-map on exactly the same piece of code!? > > > > [...] > > > > translated from Scheme+ to Scheme: > > (define unified-minterms-set-1 (map function-unify-minterms-list > > minterms-set)) ;;(par-map function-unify-minterms-list minterms-set)) > > The definition of 'function-unify-minterms-list' and 'minterms-set' is > missing. Without a test case, we can only speculate what's going on. > (E.g., maybe it grabs a mutex). > > Greetings, > Maxime. > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-12 20:20 ` Damien Mattei @ 2022-10-12 20:27 ` Damien Mattei 2022-10-12 21:29 ` Zelphir Kaltstahl 2022-10-12 21:44 ` Maxime Devos 1 sibling, 1 reply; 27+ messages in thread From: Damien Mattei @ 2022-10-12 20:27 UTC (permalink / raw) To: Maxime Devos; +Cc: guile-user, guile-devel https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1674 i commited the current version of code here with all files but it is huge.... :-/ On Wed, Oct 12, 2022 at 10:20 PM Damien Mattei <damien.mattei@gmail.com> wrote: > Mutex? i do not think code has situation where dead lock could happen, it > is a code about minimalising logic expressions, it uses minterms , minterms > set is a set of minterms :like this: > > example: > ((1 1 0) (1 1 1)) will be unified : (1 1 x) > because 0 and 1 are replaced by x > the minterms-set could have thousands of pair (mathematic not lisp) > minterms to unify > if there is more than one x as result there is no need to continue so i > escape with a continuation: > > minterms-set = > { > ((1 0 1 0) (1 1 1 0)) > ((1 0 1 0) (1 1 0 1)) > ((1 0 1 0) (1 0 1 1)) > ((1 0 1 0) (0 1 1 1)) > ((0 1 1 0) (1 1 1 0)) > ((0 1 1 0) (1 1 0 1)) > ((0 1 1 0) (1 0 1 1)) > ((0 1 1 0) (0 1 1 1)) > ((0 1 0 1) (1 1 1 0)) > ((0 1 0 1) (1 1 0 1)) > ((0 1 0 1) (1 0 1 1)) > ((0 1 0 1) (0 1 1 1)) > ((0 0 1 1) (1 1 1 0)) > ((0 0 1 1) (1 1 0 1)) > ((0 0 1 1) (1 0 1 1)) > ((0 0 1 1) (0 1 1 1)) > } > > replace { } by () to have the list, other example at another level : > > minterms-set = > { > ((0 x 1 1) (x 1 1 1)) > ((0 x 1 1) (1 x 1 1)) > ((0 x 1 1) (1 1 x 1)) > ((0 x 1 1) (1 1 1 x)) > ((x 0 1 1) (x 1 1 1)) > ((x 0 1 1) (1 x 1 1)) > ((x 0 1 1) (1 1 x 1)) > ((x 0 1 1) (1 1 1 x)) > ((0 1 x 1) (x 1 1 1)) > ((0 1 x 1) (1 x 1 1)) > ((0 1 x 1) (1 1 x 1)) > ((0 1 x 1) (1 1 1 x)) > ((x 1 0 1) (x 1 1 1)) > ((x 1 0 1) (1 x 1 1)) > ((x 1 0 1) (1 1 x 1)) > ((x 1 0 1) (1 1 1 x)) > ((0 1 1 x) (x 1 1 1)) > ((0 1 1 x) (1 x 1 1)) > ((0 1 1 x) (1 1 x 1)) > ((0 1 1 x) (1 1 1 x)) > ((x 1 1 0) (x 1 1 1)) > ((x 1 1 0) (1 x 1 1)) > ((x 1 1 0) (1 1 x 1)) > ((x 1 1 0) (1 1 1 x)) > ((1 0 1 x) (x 1 1 1)) > ((1 0 1 x) (1 x 1 1)) > ((1 0 1 x) (1 1 x 1)) > ((1 0 1 x) (1 1 1 x)) > ((1 x 1 0) (x 1 1 1)) > ((1 x 1 0) (1 x 1 1)) > ((1 x 1 0) (1 1 x 1)) > ((1 x 1 0) (1 1 1 x)) > } > > here we see some minterms are already unified > > it is not easy to read even by me because i wrote the code many years ago > and is split in many files, but here it is: > > (par-map function-unify-minterms-list minterms-set) > > {function-unify-minterms-list <+ (λ (L) (apply > function-unify-two-minterms-and-tag L))} > > (define (unify-two-minterms mt1 mt2) > (function-map-with-escaping-by-kontinuation2 > (macro-function-compare-2-bits-with-continuation) mt1 mt2)) > > ;; (function-map-with-escaping-by-kontinuation2 > (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 0) '(1 > 1 0 1 1 1 1 1)) > > ;; list1 = (1 1 0 1 0 1 1 0) > ;; more-lists = ((1 1 0 1 1 1 1 1)) > ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 1)) > ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> > > ;; #f > ;; > ;; (function-map-with-escaping-by-kontinuation2 > (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 0) '(1 > 1 0 1 1 1 1 0)) > > ;; list1 = (1 1 0 1 0 1 1 0) > ;; more-lists = ((1 1 0 1 1 1 1 0)) > ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 0)) > ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> > > ;; '(1 1 0 1 x 1 1 0) > (define (function-map-with-escaping-by-kontinuation2 clozure list1 . > more-lists) > (call/cc (lambda (kontinuation) > (let ((lists (cons list1 more-lists)) > (funct-continu ;; this function have the kontinuation in his environment > (lambda (arg1 . more-args) > (let ((args (cons arg1 more-args))) > (apply clozure kontinuation args))))) ;; a tester: (apply clozure (cons > conti args)) > > ;; (newline) > ;; (dv list1) > ;; (dv more-lists) > ;; (dv lists) > ;; (dv clozure) > ;; (newline) > > (apply map funct-continu lists))))) > > (define-syntax macro-function-compare-2-bits-with-continuation ;; > continuation version of macro-compare-2-bits > ;; i need a macro because of external function to the clozure > (syntax-rules () > ((_) (let ((cnt 0)) ;; counter > (lambda (continuation b1 b2) (if (equal? b1 b2) > b1 > (begin > (set! cnt (add1 cnt)) ;; we leave with continuation in case cpt > 1, we > can have used a flag too instead of a counter > (when (> cnt 1) (continuation #f)) ;; escaping with the continuation > 'x))))))) ;; return x in case of (b1,b2) = (O,1) or (1,0) > > what could have caused mutex if in the latter definition above (let ((cnt > 0)) ;; counter was defined at top level and shared by all threads!!! yes > there could have be some mutex but this is not the case, i think even all > function are pure so why is it more slow with // than without? > Damien > > On Wed, Oct 12, 2022 at 8:45 PM Maxime Devos <maximedevos@telenet.be> > wrote: > >> On 12-10-2022 19:19, Damien Mattei wrote: >> > Hello, >> > all is in the title, i test on a approximately 30000 element list , i >> got >> > 9s with map and 3min 30s with par-map on exactly the same piece of >> code!? >> > >> > [...] >> > >> > translated from Scheme+ to Scheme: >> > (define unified-minterms-set-1 (map function-unify-minterms-list >> > minterms-set)) ;;(par-map function-unify-minterms-list minterms-set)) >> >> The definition of 'function-unify-minterms-list' and 'minterms-set' is >> missing. Without a test case, we can only speculate what's going on. >> (E.g., maybe it grabs a mutex). >> >> Greetings, >> Maxime. >> > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-12 20:27 ` Damien Mattei @ 2022-10-12 21:29 ` Zelphir Kaltstahl 2022-10-14 8:21 ` Damien Mattei 2022-10-25 9:07 ` Mikael Djurfeldt 0 siblings, 2 replies; 27+ messages in thread From: Zelphir Kaltstahl @ 2022-10-12 21:29 UTC (permalink / raw) To: Damien Mattei; +Cc: guile-user, guile-devel Hi! On 10/12/22 22:27, Damien Mattei wrote: > https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1674 > > i commited the current version of code here with all files but it is > huge.... :-/ > > On Wed, Oct 12, 2022 at 10:20 PM Damien Mattei <damien.mattei@gmail.com> > wrote: > >> Mutex? i do not think code has situation where dead lock could happen, it >> is a code about minimalising logic expressions, it uses minterms , minterms >> set is a set of minterms :like this: >> >> example: >> ((1 1 0) (1 1 1)) will be unified : (1 1 x) >> because 0 and 1 are replaced by x >> the minterms-set could have thousands of pair (mathematic not lisp) >> minterms to unify >> if there is more than one x as result there is no need to continue so i >> escape with a continuation: >> >> minterms-set = >> { >> ((1 0 1 0) (1 1 1 0)) >> ((1 0 1 0) (1 1 0 1)) >> ((1 0 1 0) (1 0 1 1)) >> ((1 0 1 0) (0 1 1 1)) >> ((0 1 1 0) (1 1 1 0)) >> ((0 1 1 0) (1 1 0 1)) >> ((0 1 1 0) (1 0 1 1)) >> ((0 1 1 0) (0 1 1 1)) >> ((0 1 0 1) (1 1 1 0)) >> ((0 1 0 1) (1 1 0 1)) >> ((0 1 0 1) (1 0 1 1)) >> ((0 1 0 1) (0 1 1 1)) >> ((0 0 1 1) (1 1 1 0)) >> ((0 0 1 1) (1 1 0 1)) >> ((0 0 1 1) (1 0 1 1)) >> ((0 0 1 1) (0 1 1 1)) >> } >> >> replace { } by () to have the list, other example at another level : >> >> minterms-set = >> { >> ((0 x 1 1) (x 1 1 1)) >> ((0 x 1 1) (1 x 1 1)) >> ((0 x 1 1) (1 1 x 1)) >> ((0 x 1 1) (1 1 1 x)) >> ((x 0 1 1) (x 1 1 1)) >> ((x 0 1 1) (1 x 1 1)) >> ((x 0 1 1) (1 1 x 1)) >> ((x 0 1 1) (1 1 1 x)) >> ((0 1 x 1) (x 1 1 1)) >> ((0 1 x 1) (1 x 1 1)) >> ((0 1 x 1) (1 1 x 1)) >> ((0 1 x 1) (1 1 1 x)) >> ((x 1 0 1) (x 1 1 1)) >> ((x 1 0 1) (1 x 1 1)) >> ((x 1 0 1) (1 1 x 1)) >> ((x 1 0 1) (1 1 1 x)) >> ((0 1 1 x) (x 1 1 1)) >> ((0 1 1 x) (1 x 1 1)) >> ((0 1 1 x) (1 1 x 1)) >> ((0 1 1 x) (1 1 1 x)) >> ((x 1 1 0) (x 1 1 1)) >> ((x 1 1 0) (1 x 1 1)) >> ((x 1 1 0) (1 1 x 1)) >> ((x 1 1 0) (1 1 1 x)) >> ((1 0 1 x) (x 1 1 1)) >> ((1 0 1 x) (1 x 1 1)) >> ((1 0 1 x) (1 1 x 1)) >> ((1 0 1 x) (1 1 1 x)) >> ((1 x 1 0) (x 1 1 1)) >> ((1 x 1 0) (1 x 1 1)) >> ((1 x 1 0) (1 1 x 1)) >> ((1 x 1 0) (1 1 1 x)) >> } >> >> here we see some minterms are already unified >> >> it is not easy to read even by me because i wrote the code many years ago >> and is split in many files, but here it is: >> >> (par-map function-unify-minterms-list minterms-set) >> >> {function-unify-minterms-list <+ (λ (L) (apply >> function-unify-two-minterms-and-tag L))} >> >> (define (unify-two-minterms mt1 mt2) >> (function-map-with-escaping-by-kontinuation2 >> (macro-function-compare-2-bits-with-continuation) mt1 mt2)) >> >> ;; (function-map-with-escaping-by-kontinuation2 >> (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 0) '(1 >> 1 0 1 1 1 1 1)) >> >> ;; list1 = (1 1 0 1 0 1 1 0) >> ;; more-lists = ((1 1 0 1 1 1 1 1)) >> ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 1)) >> ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> >> >> ;; #f >> ;; >> ;; (function-map-with-escaping-by-kontinuation2 >> (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 0) '(1 >> 1 0 1 1 1 1 0)) >> >> ;; list1 = (1 1 0 1 0 1 1 0) >> ;; more-lists = ((1 1 0 1 1 1 1 0)) >> ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 0)) >> ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> >> >> ;; '(1 1 0 1 x 1 1 0) >> (define (function-map-with-escaping-by-kontinuation2 clozure list1 . >> more-lists) >> (call/cc (lambda (kontinuation) >> (let ((lists (cons list1 more-lists)) >> (funct-continu ;; this function have the kontinuation in his environment >> (lambda (arg1 . more-args) >> (let ((args (cons arg1 more-args))) >> (apply clozure kontinuation args))))) ;; a tester: (apply clozure (cons >> conti args)) >> >> ;; (newline) >> ;; (dv list1) >> ;; (dv more-lists) >> ;; (dv lists) >> ;; (dv clozure) >> ;; (newline) >> >> (apply map funct-continu lists))))) >> >> (define-syntax macro-function-compare-2-bits-with-continuation ;; >> continuation version of macro-compare-2-bits >> ;; i need a macro because of external function to the clozure >> (syntax-rules () >> ((_) (let ((cnt 0)) ;; counter >> (lambda (continuation b1 b2) (if (equal? b1 b2) >> b1 >> (begin >> (set! cnt (add1 cnt)) ;; we leave with continuation in case cpt > 1, we >> can have used a flag too instead of a counter >> (when (> cnt 1) (continuation #f)) ;; escaping with the continuation >> 'x))))))) ;; return x in case of (b1,b2) = (O,1) or (1,0) >> >> what could have caused mutex if in the latter definition above (let ((cnt >> 0)) ;; counter was defined at top level and shared by all threads!!! yes >> there could have be some mutex but this is not the case, i think even all >> function are pure so why is it more slow with // than without? >> Damien >> >> On Wed, Oct 12, 2022 at 8:45 PM Maxime Devos <maximedevos@telenet.be> >> wrote: >> >>> On 12-10-2022 19:19, Damien Mattei wrote: >>>> Hello, >>>> all is in the title, i test on a approximately 30000 element list , i >>> got >>>> 9s with map and 3min 30s with par-map on exactly the same piece of >>> code!? >>> > [...] >>> > >>>> translated from Scheme+ to Scheme: >>>> (define unified-minterms-set-1 (map function-unify-minterms-list >>>> minterms-set)) ;;(par-map function-unify-minterms-list minterms-set)) >>> The definition of 'function-unify-minterms-list' and 'minterms-set' is >>> missing. Without a test case, we can only speculate what's going on. >>> (E.g., maybe it grabs a mutex). >>> >>> Greetings, >>> Maxime. I don't want to scare anyone, just maybe warn about parallel map. I once tried to use Guile's parallel map function for a decision tree implementation (https://notabug.org/ZelphirKaltstahl/guile-ml/src/cf666801fea91c9fa8fa290764ff6c60b7f3949d/decision-tree.scm), where each branch while learning the tree would call parallel map again for sub branches and so on. Somehow it made Guile crash (I don't have the error message any longer, but I did post about it on the mailing list back then.). I never figured out, what went wrong. All I had was pure function calls and math inside the thing that parallel map was supposed to run. Ultimately I simply tried other parallelism constructs and when I switched to using futures instead, everything worked fine, no crashes, no errors. Since that time, I did not use parallel map and instead used futures. Recently I made a parallelization thing for solving exercises of Project Euler using multiple cores, so that some solutions are calculated faster. Maybe this can help or can be adapted to another use case: https://notabug.org/ZelphirKaltstahl/guile-project-euler-solutions/src/ebb19b11b465903105924adb6252f1e2ecf63859/lib/parallelism.scm#L11-L30 It expects ranges of things, which are called `segments` in the code. Usually ranges of numbers for Project Euler things. Here is the code to split a range into segments: https://notabug.org/ZelphirKaltstahl/guile-project-euler-solutions/src/ebb19b11b465903105924adb6252f1e2ecf63859/lib/segment.scm (Check any solution using it for an example.) So this might be a bit too specific for general parallel things, but I guess one could change the way futures are used in `run-in-parallel`, to fit any other purpose. Best regards, Zelphir -- repositories: https://notabug.org/ZelphirKaltstahl ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-12 21:29 ` Zelphir Kaltstahl @ 2022-10-14 8:21 ` Damien Mattei 2022-10-14 8:38 ` Zelphir Kaltstahl 2022-10-25 9:07 ` Mikael Djurfeldt 1 sibling, 1 reply; 27+ messages in thread From: Damien Mattei @ 2022-10-14 8:21 UTC (permalink / raw) To: Zelphir Kaltstahl; +Cc: guile-user, guile-devel yes Zelphir i think there is a problem in the threading part of guile, whatever the code is ,it run well the first time, and after is unstable. Long ago at the very begin of Java language on my master project at university i experienced same problem with Java "green" threads, under windows and/or linux ,i can't remember. I'm trying your code and future, which have perheaps also the portability with other schemes, future can provide "light" // , with carefull code it could be ok. in your segment.scm code ,is segment-count possibly replaced by the number of available CPUs or nodes, if i understand well? Regards, Damien On Wed, Oct 12, 2022 at 11:29 PM Zelphir Kaltstahl < zelphirkaltstahl@posteo.de> wrote: > Hi! > > On 10/12/22 22:27, Damien Mattei wrote: > > > https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1674 > > > > i commited the current version of code here with all files but it is > > huge.... :-/ > > > > On Wed, Oct 12, 2022 at 10:20 PM Damien Mattei <damien.mattei@gmail.com> > > wrote: > > > >> Mutex? i do not think code has situation where dead lock could happen, > it > >> is a code about minimalising logic expressions, it uses minterms , > minterms > >> set is a set of minterms :like this: > >> > >> example: > >> ((1 1 0) (1 1 1)) will be unified : (1 1 x) > >> because 0 and 1 are replaced by x > >> the minterms-set could have thousands of pair (mathematic not lisp) > >> minterms to unify > >> if there is more than one x as result there is no need to continue so i > >> escape with a continuation: > >> > >> minterms-set = > >> { > >> ((1 0 1 0) (1 1 1 0)) > >> ((1 0 1 0) (1 1 0 1)) > >> ((1 0 1 0) (1 0 1 1)) > >> ((1 0 1 0) (0 1 1 1)) > >> ((0 1 1 0) (1 1 1 0)) > >> ((0 1 1 0) (1 1 0 1)) > >> ((0 1 1 0) (1 0 1 1)) > >> ((0 1 1 0) (0 1 1 1)) > >> ((0 1 0 1) (1 1 1 0)) > >> ((0 1 0 1) (1 1 0 1)) > >> ((0 1 0 1) (1 0 1 1)) > >> ((0 1 0 1) (0 1 1 1)) > >> ((0 0 1 1) (1 1 1 0)) > >> ((0 0 1 1) (1 1 0 1)) > >> ((0 0 1 1) (1 0 1 1)) > >> ((0 0 1 1) (0 1 1 1)) > >> } > >> > >> replace { } by () to have the list, other example at another level : > >> > >> minterms-set = > >> { > >> ((0 x 1 1) (x 1 1 1)) > >> ((0 x 1 1) (1 x 1 1)) > >> ((0 x 1 1) (1 1 x 1)) > >> ((0 x 1 1) (1 1 1 x)) > >> ((x 0 1 1) (x 1 1 1)) > >> ((x 0 1 1) (1 x 1 1)) > >> ((x 0 1 1) (1 1 x 1)) > >> ((x 0 1 1) (1 1 1 x)) > >> ((0 1 x 1) (x 1 1 1)) > >> ((0 1 x 1) (1 x 1 1)) > >> ((0 1 x 1) (1 1 x 1)) > >> ((0 1 x 1) (1 1 1 x)) > >> ((x 1 0 1) (x 1 1 1)) > >> ((x 1 0 1) (1 x 1 1)) > >> ((x 1 0 1) (1 1 x 1)) > >> ((x 1 0 1) (1 1 1 x)) > >> ((0 1 1 x) (x 1 1 1)) > >> ((0 1 1 x) (1 x 1 1)) > >> ((0 1 1 x) (1 1 x 1)) > >> ((0 1 1 x) (1 1 1 x)) > >> ((x 1 1 0) (x 1 1 1)) > >> ((x 1 1 0) (1 x 1 1)) > >> ((x 1 1 0) (1 1 x 1)) > >> ((x 1 1 0) (1 1 1 x)) > >> ((1 0 1 x) (x 1 1 1)) > >> ((1 0 1 x) (1 x 1 1)) > >> ((1 0 1 x) (1 1 x 1)) > >> ((1 0 1 x) (1 1 1 x)) > >> ((1 x 1 0) (x 1 1 1)) > >> ((1 x 1 0) (1 x 1 1)) > >> ((1 x 1 0) (1 1 x 1)) > >> ((1 x 1 0) (1 1 1 x)) > >> } > >> > >> here we see some minterms are already unified > >> > >> it is not easy to read even by me because i wrote the code many years > ago > >> and is split in many files, but here it is: > >> > >> (par-map function-unify-minterms-list minterms-set) > >> > >> {function-unify-minterms-list <+ (λ (L) (apply > >> function-unify-two-minterms-and-tag L))} > >> > >> (define (unify-two-minterms mt1 mt2) > >> (function-map-with-escaping-by-kontinuation2 > >> (macro-function-compare-2-bits-with-continuation) mt1 mt2)) > >> > >> ;; (function-map-with-escaping-by-kontinuation2 > >> (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 0) > '(1 > >> 1 0 1 1 1 1 1)) > >> > >> ;; list1 = (1 1 0 1 0 1 1 0) > >> ;; more-lists = ((1 1 0 1 1 1 1 1)) > >> ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 1)) > >> ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> > >> > >> ;; #f > >> ;; > >> ;; (function-map-with-escaping-by-kontinuation2 > >> (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 0) > '(1 > >> 1 0 1 1 1 1 0)) > >> > >> ;; list1 = (1 1 0 1 0 1 1 0) > >> ;; more-lists = ((1 1 0 1 1 1 1 0)) > >> ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 0)) > >> ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> > >> > >> ;; '(1 1 0 1 x 1 1 0) > >> (define (function-map-with-escaping-by-kontinuation2 clozure list1 . > >> more-lists) > >> (call/cc (lambda (kontinuation) > >> (let ((lists (cons list1 more-lists)) > >> (funct-continu ;; this function have the kontinuation in his > environment > >> (lambda (arg1 . more-args) > >> (let ((args (cons arg1 more-args))) > >> (apply clozure kontinuation args))))) ;; a tester: (apply clozure (cons > >> conti args)) > >> > >> ;; (newline) > >> ;; (dv list1) > >> ;; (dv more-lists) > >> ;; (dv lists) > >> ;; (dv clozure) > >> ;; (newline) > >> > >> (apply map funct-continu lists))))) > >> > >> (define-syntax macro-function-compare-2-bits-with-continuation ;; > >> continuation version of macro-compare-2-bits > >> ;; i need a macro because of external function to the clozure > >> (syntax-rules () > >> ((_) (let ((cnt 0)) ;; counter > >> (lambda (continuation b1 b2) (if (equal? b1 b2) > >> b1 > >> (begin > >> (set! cnt (add1 cnt)) ;; we leave with continuation in case cpt > > 1, we > >> can have used a flag too instead of a counter > >> (when (> cnt 1) (continuation #f)) ;; escaping with the continuation > >> 'x))))))) ;; return x in case of (b1,b2) = (O,1) or (1,0) > >> > >> what could have caused mutex if in the latter definition above (let > ((cnt > >> 0)) ;; counter was defined at top level and shared by all threads!!! yes > >> there could have be some mutex but this is not the case, i think even > all > >> function are pure so why is it more slow with // than without? > >> Damien > >> > >> On Wed, Oct 12, 2022 at 8:45 PM Maxime Devos <maximedevos@telenet.be> > >> wrote: > >> > >>> On 12-10-2022 19:19, Damien Mattei wrote: > >>>> Hello, > >>>> all is in the title, i test on a approximately 30000 element list , i > >>> got > >>>> 9s with map and 3min 30s with par-map on exactly the same piece of > >>> code!? > >>> > [...] > >>> > > >>>> translated from Scheme+ to Scheme: > >>>> (define unified-minterms-set-1 (map function-unify-minterms-list > >>>> minterms-set)) ;;(par-map function-unify-minterms-list minterms-set)) > >>> The definition of 'function-unify-minterms-list' and 'minterms-set' is > >>> missing. Without a test case, we can only speculate what's going on. > >>> (E.g., maybe it grabs a mutex). > >>> > >>> Greetings, > >>> Maxime. > I don't want to scare anyone, just maybe warn about parallel map. I once > tried > to use Guile's parallel map function for a decision tree implementation > ( > https://notabug.org/ZelphirKaltstahl/guile-ml/src/cf666801fea91c9fa8fa290764ff6c60b7f3949d/decision-tree.scm), > > where each branch while learning the tree would call parallel map again > for sub > branches and so on. Somehow it made Guile crash (I don't have the error > message > any longer, but I did post about it on the mailing list back then.). I > never > figured out, what went wrong. All I had was pure function calls and math > inside > the thing that parallel map was supposed to run. > > Ultimately I simply tried other parallelism constructs and when I switched > to > using futures instead, everything worked fine, no crashes, no errors. > > Since that time, I did not use parallel map and instead used futures. > Recently I > made a parallelization thing for solving exercises of Project Euler using > multiple cores, so that some solutions are calculated faster. Maybe this > can > help or can be adapted to another use case: > > > https://notabug.org/ZelphirKaltstahl/guile-project-euler-solutions/src/ebb19b11b465903105924adb6252f1e2ecf63859/lib/parallelism.scm#L11-L30 > > It expects ranges of things, which are called `segments` in the code. > Usually > ranges of numbers for Project Euler things. Here is the code to split a > range > into segments: > > > https://notabug.org/ZelphirKaltstahl/guile-project-euler-solutions/src/ebb19b11b465903105924adb6252f1e2ecf63859/lib/segment.scm > > (Check any solution using it for an example.) > > So this might be a bit too specific for general parallel things, but I > guess one > could change the way futures are used in `run-in-parallel`, to fit any > other > purpose. > > Best regards, > Zelphir > > -- > repositories: https://notabug.org/ZelphirKaltstahl > > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-14 8:21 ` Damien Mattei @ 2022-10-14 8:38 ` Zelphir Kaltstahl 2022-10-17 13:17 ` Damien Mattei 0 siblings, 1 reply; 27+ messages in thread From: Zelphir Kaltstahl @ 2022-10-14 8:38 UTC (permalink / raw) To: Damien Mattei; +Cc: guile-user, guile-devel [-- Attachment #1: Type: text/plain, Size: 1723 bytes --] Hello Damien, On 10/14/22 10:21, Damien Mattei wrote: > yes Zelphir i think there is a problem in the threading part of guile, > whatever the code is ,it run well the first time, and after is unstable. Long > ago at the very begin of Java language on my master project at university i > experienced same problem with Java "green" threads, under windows and/or linux > ,i can't remember. > > I'm trying your code and future, which have perheaps also the portability with > other schemes, future can provide "light" // , with carefull code it could be ok. > > in your segment.scm code ,is segment-count possibly replaced by the number of > available CPUs or nodes, if i understand well? > > Regards, > Damien Correct. For each segment one future is used. However, there are scenarios, where one would rather want to interleave the numbers of the whole range, to have a "fairer" workload per future, for example: (1 2 3 4 5 6 7 8 9) -> (1 4 7), (2 5 8), (3 6 9) instead of -> (1 2 3) (4 5 6) (7 8 9) (I seem to remember this to be the case for Mandelbrot set calculations, but might be wrong.) But that is all a matter of forming some segments and what a segment is, not really part of the logic of creating futures. So one could create then in any way that fits ones use-case. I have not generalized that segment logic that far, but it is doable. Anyway, if anyone more knowledgeable could chime in on what the performance differences between futures and parallel map are, that would be great! Or pointing out some flaws that this kind of future usage might have. Or when the point is reached to switch to guile-fibers library. Regards, Zelphir -- repositories:https://notabug.org/ZelphirKaltstahl [-- Attachment #2: Type: text/html, Size: 3110 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-14 8:38 ` Zelphir Kaltstahl @ 2022-10-17 13:17 ` Damien Mattei 2022-10-22 16:01 ` Damien Mattei 0 siblings, 1 reply; 27+ messages in thread From: Damien Mattei @ 2022-10-17 13:17 UTC (permalink / raw) To: Zelphir Kaltstahl; +Cc: guile-user, guile-devel Hello, sorry for my late answer ( i wrote the code friday but i could only debug today, being busy and on travel last week-end) i modified my code to works with 'futures' , the speed is now incredible !!! (and it computes exact) the speed seems multiplied by even more than the number of CPUs (6): cat /proc/cpuinfo | grep processor processor : 0 processor : 1 processor : 2 processor : 3 processor : 4 processor : 5 https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1900 (declare minterms-vector unified-minterms-vector-1) (define (funct-unify-minterms-set-1-unit-future set1 set2) {function-unify-minterms-list <+ (λ (L) (apply function-unify-two-minterms-and-tag L))} ;; note : sorting is useless {minterms-set <+ (product-set-with-set-imperative-sorted set1 set2)} ;;(product-set-with-set-imperative set1 set2)} ;;(product-set-with-set set1 set2)} ;;(associate-set-with-set set1 set2)} ;; set multiplication : create list of pair of minterms {minterms-vector <- (list->vector minterms-set)} {minterms-vector-length <+ (vector-length minterms-vector)} {nb-procs <+ (current-processor-count)} {segmts <+ (segment 0 {minterms-vector-length - 1} nb-procs)} ;; compute the segments {unified-minterms-vector-1 <- (make-vector minterms-vector-length #f)} (run-in-parallel segmts proc-unify-minterms-seg) ;; run the parallel code {unified-minterms-set-1 <+ (vector->list unified-minterms-vector-1)} {unified-minterms-set-2 <+ (filter (λ (x) x) unified-minterms-set-1)} ;; remove #f results {unified-minterms-set <+ (remove-duplicates-sorted unified-minterms-set-2)} ;; uniq unified-minterms-set) i keeped your 'segment' definitions to index an array of data after convert it from list to vector (list->vector) which probably consume additional time on big data list ( i had more than 1000000 element list lengths at some point) i used a simplified version of run-in parallel (that do not do 'reduce after processing data): https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1794 the computation on a segment is done by those functions: https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1842 {function-unify-minterms-list <+ (λ (L) (apply function-unify-two-minterms-and-tag L))} ;; proc to be called with futures (define (proc-unify-minterms-seg seg) {start <+ (segment-start seg)} {end <+ (segment-end seg)} (for ({i <+ start} {i <= end} {i <- {i + 1}}) {mtL <+ {minterms-vector[i]}} {unified-minterms-vector-1[i] <- (function-unify-minterms-list mtL)})) i use those code in another program symbolically to compute a value named Cn: C0 = T C1 = T C2 = T C3 = (B1 ∨ B2) C4 = (B2 ∨ (B1 ∧ B3)) C5 = ((B1 ∧ B3) ∨ (B2 ∧ B3) ∨ (B2 ∧ B4) ∨ (B3 ∧ B4)) C6 = ((B1 ∧ B3 ∧ B5) ∨ (B2 ∧ B3 ∧ B5) ∨ (B2 ∧ B4) ∨ (B3 ∧ B4) ∨ (B4 ∧ B5)) C7 = ((B1 ∧ B3 ∧ B5) ∨ (B2 ∧ B3 ∧ B5) ∨ (B2 ∧ B4 ∧ B6) ∨ (B3 ∧ B4 ∧ B6) ∨ (B4 ∧ B5) ∨ (B5 ∧ B6)) C8 = ((B1 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B4 ∧ B6) ∨ (B3 ∧ B4 ∧ B6) ∨ (B4 ∧ B5 ∧ B7) ∨ (B5 ∧ B6) ∨ (B6 ∧ B7)) C9 = ((B1 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B4 ∧ B6 ∧ B8) ∨ (B3 ∧ B4 ∧ B6 ∧ B8) ∨ (B4 ∧ B5 ∧ B7) ∨ (B5 ∧ B6 ∧ B8) ∨ (B6 ∧ B7) ∨ (B7 ∧ B8)) from C1 to C9 used to be fast,less than a minute for the whole with or without // C10 = ((B1 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B2 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B2 ∧ B4 ∧ B6 ∧ B8) ∨ (B3 ∧ B4 ∧ B6 ∧ B8) ∨ (B4 ∧ B5 ∧ B7 ∧ B9) ∨ (B5 ∧ B6 ∧ B8) ∨ (B6 ∧ B7 ∧ B9) ∨ (B7 ∧ B8) ∨ (B8 ∧ B9)) C10 takes a few minutes but C11 used to take one day before // with 'future' and i got now the result during less than one hour!!! C11 = ((B1 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B10 ∧ B2 ∧ B4 ∧ B6 ∧ B8) ∨ (B10 ∧ B3 ∧ B4 ∧ B6 ∧ B8) ∨ (B10 ∧ B5 ∧ B6 ∧ B8) ∨ (B10 ∧ B7 ∧ B8) ∨ (B10 ∧ B9) ∨ (B2 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B4 ∧ B5 ∧ B7 ∧ B9) ∨ (B6 ∧ B7 ∧ B9) ∨ (B8 ∧ B9)) i never got C12 in the past ,even with 7 days of computation! and i got it today during the lunchbreak !!! C12 = ((B1 ∧ B11 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B10 ∧ B11) ∨ (B10 ∧ B2 ∧ B4 ∧ B6 ∧ B8) ∨ (B10 ∧ B3 ∧ B4 ∧ B6 ∧ B8) ∨ (B10 ∧ B5 ∧ B6 ∧ B8) ∨ (B10 ∧ B7 ∧ B8) ∨ (B10 ∧ B9) ∨ (B11 ∧ B2 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B11 ∧ B4 ∧ B5 ∧ B7 ∧ B9) ∨ (B11 ∧ B6 ∧ B7 ∧ B9) ∨ (B11 ∧ B8 ∧ B9)) (note that a wise people can find a general formula for Cn based on Cn-1 but that is another (mathematical) story....) i'm computing C13 but i see that it consumes 12gb out of 16gb of my system ! and stopped on the linux box : GC Warning: Repeated allocation of very large block (appr. size 510935040): May lead to memory leak and poor performance Processus arrêté but still running on the Mac laptop...ok will see that but i think that the data set is now huge and there is noting that can be done with that... note that there is still an hash table used in function-unify-two-minterms-and-tag and i will use another data structure and algo to avoid that, i feared that the concurrent access to hash table can cause the guile 'future' to crash or fails or to slow down the process but not! result is incredibly fast.Also i use continuation and i read it can cause problem with 'future' i will improve that too... I will see where i can improve the algo and data structure to optimize again but this is already really good. Thanks Damien On Fri, Oct 14, 2022 at 10:39 AM Zelphir Kaltstahl < zelphirkaltstahl@posteo.de> wrote: > Hello Damien, > On 10/14/22 10:21, Damien Mattei wrote: > > yes Zelphir i think there is a problem in the threading part of guile, > whatever the code is ,it run well the first time, and after is unstable. > Long ago at the very begin of Java language on my master project at > university i experienced same problem with Java "green" threads, under > windows and/or linux ,i can't remember. > > I'm trying your code and future, which have perheaps also the portability > with other schemes, future can provide "light" // , with carefull code it > could be ok. > > in your segment.scm code ,is segment-count possibly replaced by the number > of available CPUs or nodes, if i understand well? > > Regards, > Damien > > Correct. For each segment one future is used. > > However, there are scenarios, where one would rather want to interleave > the numbers of the whole range, to have a "fairer" workload per future, for > example: > > (1 2 3 4 5 6 7 8 9) > > -> (1 4 7), (2 5 8), (3 6 9) > > instead of > > -> (1 2 3) (4 5 6) (7 8 9) > > (I seem to remember this to be the case for Mandelbrot set calculations, > but might be wrong.) > > But that is all a matter of forming some segments and what a segment is, > not really part of the logic of creating futures. So one could create then > in any way that fits ones use-case. I have not generalized that segment > logic that far, but it is doable. > > Anyway, if anyone more knowledgeable could chime in on what the > performance differences between futures and parallel map are, that would be > great! Or pointing out some flaws that this kind of future usage might > have. Or when the point is reached to switch to guile-fibers library. > > Regards, > Zelphir > > -- > repositories: https://notabug.org/ZelphirKaltstahl > > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-17 13:17 ` Damien Mattei @ 2022-10-22 16:01 ` Damien Mattei 2022-10-23 1:06 ` Damien Mattei 0 siblings, 1 reply; 27+ messages in thread From: Damien Mattei @ 2022-10-22 16:01 UTC (permalink / raw) To: Zelphir Kaltstahl; +Cc: guile-user, guile-devel just for the fun things, i just find that the parallelized results are false :-) even for low indices: the non // result: C5 = ((B1 ∧ B3) ∨ (B2 ∧ B3) ∨ (B2 ∧ B4)) is different than the parallelized result below: C5 = ((B1 ∧ B3) ∨ (B2 ∧ B3) ∨ (B2 ∧ B4) ∨ (B3 ∧ B4)) i have to check things again ,i think futures are easy to use but limited in solving acute // problems, such as using a global variable like an hash table... Damien On Mon, Oct 17, 2022 at 3:17 PM Damien Mattei <damien.mattei@gmail.com> wrote: > Hello, > > sorry for my late answer ( i wrote the code friday but i could only debug > today, being busy and on travel last week-end) > > i modified my code to works with 'futures' , the speed is now incredible > !!! (and it computes exact) > the speed seems multiplied by even more than the number of CPUs (6): > cat /proc/cpuinfo | grep processor > processor : 0 > processor : 1 > processor : 2 > processor : 3 > processor : 4 > processor : 5 > > > https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1900 > > (declare minterms-vector unified-minterms-vector-1) > > (define (funct-unify-minterms-set-1-unit-future set1 set2) > > {function-unify-minterms-list <+ (λ (L) (apply > function-unify-two-minterms-and-tag L))} > > ;; note : sorting is useless > > {minterms-set <+ (product-set-with-set-imperative-sorted set1 set2)} > ;;(product-set-with-set-imperative set1 set2)} ;;(product-set-with-set set1 > set2)} ;;(associate-set-with-set set1 set2)} ;; set multiplication : create > list of pair of minterms > > {minterms-vector <- (list->vector minterms-set)} > > {minterms-vector-length <+ (vector-length minterms-vector)} > > {nb-procs <+ (current-processor-count)} > > {segmts <+ (segment 0 {minterms-vector-length - 1} nb-procs)} ;; compute > the segments > > {unified-minterms-vector-1 <- (make-vector minterms-vector-length #f)} > > (run-in-parallel segmts proc-unify-minterms-seg) ;; run the parallel code > > {unified-minterms-set-1 <+ (vector->list unified-minterms-vector-1)} > > {unified-minterms-set-2 <+ (filter (λ (x) x) unified-minterms-set-1)} ;; > remove #f results > > {unified-minterms-set <+ (remove-duplicates-sorted > unified-minterms-set-2)} ;; uniq > > unified-minterms-set) > > i keeped your 'segment' definitions to index an array of data after > convert it from list to vector (list->vector) which probably consume > additional time on big data list ( i had more than 1000000 element list > lengths at some point) > > i used a simplified version of run-in parallel (that do not do 'reduce > after processing data): > > > https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1794 > > the computation on a segment is done by those functions: > > > https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1842 > > {function-unify-minterms-list <+ (λ (L) (apply > function-unify-two-minterms-and-tag L))} > > ;; proc to be called with futures > (define (proc-unify-minterms-seg seg) > {start <+ (segment-start seg)} > {end <+ (segment-end seg)} > (for ({i <+ start} {i <= end} {i <- {i + 1}}) > {mtL <+ {minterms-vector[i]}} > {unified-minterms-vector-1[i] <- (function-unify-minterms-list > mtL)})) > > > i use those code in another program symbolically to compute a value named > Cn: > > C0 = T > C1 = T > C2 = T > C3 = (B1 ∨ B2) > C4 = (B2 ∨ (B1 ∧ B3)) > C5 = ((B1 ∧ B3) ∨ (B2 ∧ B3) ∨ (B2 ∧ B4) ∨ (B3 ∧ B4)) > C6 = ((B1 ∧ B3 ∧ B5) ∨ (B2 ∧ B3 ∧ B5) ∨ (B2 ∧ B4) ∨ (B3 ∧ B4) ∨ (B4 ∧ B5)) > C7 = ((B1 ∧ B3 ∧ B5) ∨ (B2 ∧ B3 ∧ B5) ∨ (B2 ∧ B4 ∧ B6) ∨ (B3 ∧ B4 ∧ B6) ∨ > (B4 ∧ B5) ∨ (B5 ∧ B6)) > C8 = ((B1 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B4 ∧ B6) ∨ (B3 ∧ > B4 ∧ B6) ∨ (B4 ∧ B5 ∧ B7) ∨ (B5 ∧ B6) ∨ (B6 ∧ B7)) > C9 = ((B1 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B4 ∧ B6 ∧ B8) ∨ > (B3 ∧ B4 ∧ B6 ∧ B8) ∨ (B4 ∧ B5 ∧ B7) ∨ (B5 ∧ B6 ∧ B8) ∨ (B6 ∧ B7) ∨ (B7 ∧ > B8)) > > from C1 to C9 used to be fast,less than a minute for the whole with or > without // > > C10 = ((B1 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B2 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B2 ∧ B4 ∧ B6 > ∧ B8) ∨ (B3 ∧ B4 ∧ B6 ∧ B8) ∨ (B4 ∧ B5 ∧ B7 ∧ B9) ∨ (B5 ∧ B6 ∧ B8) ∨ (B6 ∧ > B7 ∧ B9) ∨ (B7 ∧ B8) ∨ (B8 ∧ B9)) > > C10 takes a few minutes > > but C11 used to take one day before // with 'future' and i got now the > result during less than one hour!!! > > C11 = ((B1 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B10 ∧ B2 ∧ B4 ∧ B6 ∧ B8) ∨ (B10 ∧ B3 ∧ > B4 ∧ B6 ∧ B8) ∨ (B10 ∧ B5 ∧ B6 ∧ B8) ∨ (B10 ∧ B7 ∧ B8) ∨ (B10 ∧ B9) ∨ (B2 ∧ > B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B4 ∧ B5 ∧ B7 ∧ B9) ∨ (B6 ∧ B7 ∧ B9) ∨ (B8 ∧ B9)) > > i never got C12 in the past ,even with 7 days of computation! and i got it > today during the lunchbreak !!! > > C12 = ((B1 ∧ B11 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B10 ∧ B11) ∨ (B10 ∧ B2 ∧ B4 ∧ B6 > ∧ B8) ∨ (B10 ∧ B3 ∧ B4 ∧ B6 ∧ B8) ∨ (B10 ∧ B5 ∧ B6 ∧ B8) ∨ (B10 ∧ B7 ∧ B8) > ∨ (B10 ∧ B9) ∨ (B11 ∧ B2 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B11 ∧ B4 ∧ B5 ∧ B7 ∧ B9) ∨ > (B11 ∧ B6 ∧ B7 ∧ B9) ∨ (B11 ∧ B8 ∧ B9)) > > (note that a wise people can find a general formula for Cn based on Cn-1 > but that is another (mathematical) story....) > > i'm computing C13 but i see that it consumes 12gb out of 16gb of my system > ! and stopped on the linux box : > GC Warning: Repeated allocation of very large block (appr. size 510935040): > May lead to memory leak and poor performance > Processus arrêté > but still running on the Mac laptop...ok will see that but i think that > the data set is now huge and there is noting that can be done with that... > > note that there is still an hash table used in > function-unify-two-minterms-and-tag and i will use another data structure > and algo to avoid that, i feared that the concurrent access to hash table > can cause the guile 'future' to crash or fails or to slow down the process > but not! result is incredibly fast.Also i use continuation and i read it > can cause problem with 'future' i will improve that too... > > I will see where i can improve the algo and data structure to optimize > again but this is already really good. > > Thanks > > Damien > > > On Fri, Oct 14, 2022 at 10:39 AM Zelphir Kaltstahl < > zelphirkaltstahl@posteo.de> wrote: > >> Hello Damien, >> On 10/14/22 10:21, Damien Mattei wrote: >> >> yes Zelphir i think there is a problem in the threading part of guile, >> whatever the code is ,it run well the first time, and after is unstable. >> Long ago at the very begin of Java language on my master project at >> university i experienced same problem with Java "green" threads, under >> windows and/or linux ,i can't remember. >> >> I'm trying your code and future, which have perheaps also the portability >> with other schemes, future can provide "light" // , with carefull code it >> could be ok. >> >> in your segment.scm code ,is segment-count possibly replaced by the >> number of available CPUs or nodes, if i understand well? >> >> Regards, >> Damien >> >> Correct. For each segment one future is used. >> >> However, there are scenarios, where one would rather want to interleave >> the numbers of the whole range, to have a "fairer" workload per future, for >> example: >> >> (1 2 3 4 5 6 7 8 9) >> >> -> (1 4 7), (2 5 8), (3 6 9) >> >> instead of >> >> -> (1 2 3) (4 5 6) (7 8 9) >> >> (I seem to remember this to be the case for Mandelbrot set calculations, >> but might be wrong.) >> >> But that is all a matter of forming some segments and what a segment is, >> not really part of the logic of creating futures. So one could create then >> in any way that fits ones use-case. I have not generalized that segment >> logic that far, but it is doable. >> >> Anyway, if anyone more knowledgeable could chime in on what the >> performance differences between futures and parallel map are, that would be >> great! Or pointing out some flaws that this kind of future usage might >> have. Or when the point is reached to switch to guile-fibers library. >> >> Regards, >> Zelphir >> >> -- >> repositories: https://notabug.org/ZelphirKaltstahl >> >> ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-22 16:01 ` Damien Mattei @ 2022-10-23 1:06 ` Damien Mattei 0 siblings, 0 replies; 27+ messages in thread From: Damien Mattei @ 2022-10-23 1:06 UTC (permalink / raw) To: Zelphir Kaltstahl; +Cc: guile-user, guile-devel [-- Attachment #1: Type: text/plain, Size: 14665 bytes --] after intense coding i finally got the good results, my assumption about the global variable hash table was true ,it is incompatible with 'future : the competition for the writing into the hash table breaks the code. If i do writing in hash table out of // region all is ok: a simple function to extract the hash table access: (define (tag-minterms i umt) (when umt {mt1 <+ (first {minterms-vector[i]})} {mt2 <+ (second {minterms-vector[i]})} {minterms-ht[mt1] <- #t} {minterms-ht[mt2] <- #t})) ;; proc to be called with futures (define (proc-unify-minterms-seg seg) {function-unify-minterms-list <+ (λ (L) (apply function-unify-two-minterms L))} ;;{function-unify-minterms-list <+ (λ (L) (apply function-unify-two-minterms-and-tag L))} {start <+ (segment-start seg)} {end <+ (segment-end seg)} (for ({i <+ start} {i <= end} {i <- {i + 1}}) {mtL <+ {minterms-vector[i]}} (nodebug (dv mtL)) {unified-minterms-vector-1[i] <- (function-unify-minterms-list mtL)})) (declare minterms-vector unified-minterms-vector-1) https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L2893 and the call to the code that use hash table is now completely out of the // region: (debug (display-nl "before //")) (run-in-parallel segmts proc-unify-minterms-seg) ;; run the parallel code (debug (display-nl "after //")) (vector-for-each tag-minterms unified-minterms-vector-1) ;; tag the minterms in the hash table with a partitioned vector it works because one cell is not accessed by different threads other stuff like continuation seems to work with 'future, i wanted to rewrite code with call/cc in 'future but it was too long and apparently it works,any way i do not see why call/cc would cause trouble in a thread... i think 'futures are good if you use them carefully like in OpenMP regions... in other languages. the code is very very fast now i reached C15,in a few minutes on an Apple M1 scheme@(guile-user)> (current-processor-count) $1 = 8 C15 = ((B1 ∧ B3 ∧ B4 ∧ B6 ∧ B7 ∧ B9 ∧ B10 ∧ B12 ∧ B13) ∨ (B1 ∧ B3 ∧ B4 ∧ B6 ∧ B7 ∧ B9 ∧ B10 ∧ B12 ∧ B14) ∨ (B1 ∧ B3 ∧ B4 ∧ B6 ∧ B7 ∧ B9 ∧ B11 ∧ B12 ∧ B14) ∨ (B1 ∧ B3 ∧ B4 ∧ B6 ∧ B7 ∧ B9 ∧ B11 ∧ B13) ∨ (B1 ∧ B3 ∧ B4 ∧ B6 ∧ B8 ∧ B9 ∧ B11 ∧ B12 ∧ B14) ∨ (B1 ∧ B3 ∧ B4 ∧ B6 ∧ B8 ∧ B9 ∧ B11 ∧ B13) ∨ (B1 ∧ B3 ∧ B4 ∧ B6 ∧ B8 ∧ B10 ∧ B11 ∧ B13) ∨ (B1 ∧ B3 ∧ B4 ∧ B6 ∧ B8 ∧ B10 ∧ B12 ∧ B13) ∨ (B1 ∧ B3 ∧ B4 ∧ B6 ∧ B8 ∧ B10 ∧ B12 ∧ B14) ∨ (B1 ∧ B3 ∧ B5 ∧ B6 ∧ B8 ∧ B9 ∧ B11 ∧ B12 ∧ B14) ∨ (B1 ∧ B3 ∧ B5 ∧ B6 ∧ B8 ∧ B9 ∧ B11 ∧ B13) ∨ (B1 ∧ B3 ∧ B5 ∧ B6 ∧ B8 ∧ B10 ∧ B11 ∧ B13) ∨ (B1 ∧ B3 ∧ B5 ∧ B6 ∧ B8 ∧ B10 ∧ B12 ∧ B13) ∨ (B1 ∧ B3 ∧ B5 ∧ B6 ∧ B8 ∧ B10 ∧ B12 ∧ B14) ∨ (B1 ∧ B3 ∧ B5 ∧ B7 ∧ B8 ∧ B10 ∧ B11 ∧ B13) ∨ (B1 ∧ B3 ∧ B5 ∧ B7 ∧ B8 ∧ B10 ∧ B12 ∧ B13) ∨ (B1 ∧ B3 ∧ B5 ∧ B7 ∧ B8 ∧ B10 ∧ B12 ∧ B14) ∨ (B1 ∧ B3 ∧ B5 ∧ B7 ∧ B9 ∧ B10 ∧ B12 ∧ B13) ∨ (B1 ∧ B3 ∧ B5 ∧ B7 ∧ B9 ∧ B10 ∧ B12 ∧ B14) ∨ (B1 ∧ B3 ∧ B5 ∧ B7 ∧ B9 ∧ B11 ∧ B12 ∧ B14) ∨ (B1 ∧ B3 ∧ B5 ∧ B7 ∧ B9 ∧ B11 ∧ B13) ∨ (B2 ∧ B3 ∧ B5 ∧ B6 ∧ B8 ∧ B9 ∧ B11 ∧ B12 ∧ B14) ∨ (B2 ∧ B3 ∧ B5 ∧ B6 ∧ B8 ∧ B9 ∧ B11 ∧ B13) ∨ (B2 ∧ B3 ∧ B5 ∧ B6 ∧ B8 ∧ B10 ∧ B11 ∧ B13) ∨ (B2 ∧ B3 ∧ B5 ∧ B6 ∧ B8 ∧ B10 ∧ B12 ∧ B13) ∨ (B2 ∧ B3 ∧ B5 ∧ B6 ∧ B8 ∧ B10 ∧ B12 ∧ B14) ∨ (B2 ∧ B3 ∧ B5 ∧ B7 ∧ B8 ∧ B10 ∧ B11 ∧ B13) ∨ (B2 ∧ B3 ∧ B5 ∧ B7 ∧ B8 ∧ B10 ∧ B12 ∧ B13) ∨ (B2 ∧ B3 ∧ B5 ∧ B7 ∧ B8 ∧ B10 ∧ B12 ∧ B14) ∨ (B2 ∧ B3 ∧ B5 ∧ B7 ∧ B9 ∧ B10 ∧ B12 ∧ B13) ∨ (B2 ∧ B3 ∧ B5 ∧ B7 ∧ B9 ∧ B10 ∧ B12 ∧ B14) ∨ (B2 ∧ B3 ∧ B5 ∧ B7 ∧ B9 ∧ B11 ∧ B12 ∧ B14) ∨ (B2 ∧ B3 ∧ B5 ∧ B7 ∧ B9 ∧ B11 ∧ B13) ∨ (B2 ∧ B4 ∧ B5 ∧ B7 ∧ B8 ∧ B10 ∧ B11 ∧ B13) ∨ (B2 ∧ B4 ∧ B5 ∧ B7 ∧ B8 ∧ B10 ∧ B12 ∧ B13) ∨ (B2 ∧ B4 ∧ B5 ∧ B7 ∧ B8 ∧ B10 ∧ B12 ∧ B14) ∨ (B2 ∧ B4 ∧ B5 ∧ B7 ∧ B9 ∧ B10 ∧ B12 ∧ B13) ∨ (B2 ∧ B4 ∧ B5 ∧ B7 ∧ B9 ∧ B10 ∧ B12 ∧ B14) ∨ (B2 ∧ B4 ∧ B5 ∧ B7 ∧ B9 ∧ B11 ∧ B12 ∧ B14) ∨ (B2 ∧ B4 ∧ B5 ∧ B7 ∧ B9 ∧ B11 ∧ B13) ∨ (B2 ∧ B4 ∧ B6 ∧ B7 ∧ B9 ∧ B10 ∧ B12 ∧ B13) ∨ (B2 ∧ B4 ∧ B6 ∧ B7 ∧ B9 ∧ B10 ∧ B12 ∧ B14) ∨ (B2 ∧ B4 ∧ B6 ∧ B7 ∧ B9 ∧ B11 ∧ B12 ∧ B14) ∨ (B2 ∧ B4 ∧ B6 ∧ B7 ∧ B9 ∧ B11 ∧ B13) ∨ (B2 ∧ B4 ∧ B6 ∧ B8 ∧ B9 ∧ B11 ∧ B12 ∧ B14) ∨ (B2 ∧ B4 ∧ B6 ∧ B8 ∧ B9 ∧ B11 ∧ B13) ∨ (B2 ∧ B4 ∧ B6 ∧ B8 ∧ B10 ∧ B11 ∧ B13) ∨ (B2 ∧ B4 ∧ B6 ∧ B8 ∧ B10 ∧ B12 ∧ B13) ∨ (B2 ∧ B4 ∧ B6 ∧ B8 ∧ B10 ∧ B12 ∧ B14)) and it consumes more than 2Gb in memory: PID COMMAND %CPU TIME #TH #WQ #PORT MEM PURG CMPRS PGRP PPID STATE BOOSTS %CPU_ME 15081 guile 442.8 57:24.28 17/8 0 44 *2423M* 0B 118M 15081 10551 running *0[1] 0.0000 i checked a part of the logical computation with Mathematica online and it was ok but i will do a Python program to check the logical expression again and compare speed with Sympy... and for the space complexity i do not think it can be reduced good night all On Sat, Oct 22, 2022 at 6:01 PM Damien Mattei <damien.mattei@gmail.com> wrote: > just for the fun things, i just find that the parallelized results are > false :-) even for low indices: > the non // result: C5 = ((B1 ∧ B3) ∨ (B2 ∧ B3) ∨ (B2 ∧ B4)) > is different than the parallelized result below: > C5 = ((B1 ∧ B3) ∨ (B2 ∧ B3) ∨ (B2 ∧ B4) ∨ (B3 ∧ B4)) > > i have to check things again ,i think futures are easy to use but limited > in solving acute // problems, such as using a global variable like an hash > table... > > Damien > > > > On Mon, Oct 17, 2022 at 3:17 PM Damien Mattei <damien.mattei@gmail.com> > wrote: > >> Hello, >> >> sorry for my late answer ( i wrote the code friday but i could only debug >> today, being busy and on travel last week-end) >> >> i modified my code to works with 'futures' , the speed is now incredible >> !!! (and it computes exact) >> the speed seems multiplied by even more than the number of CPUs (6): >> cat /proc/cpuinfo | grep processor >> processor : 0 >> processor : 1 >> processor : 2 >> processor : 3 >> processor : 4 >> processor : 5 >> >> >> https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1900 >> >> (declare minterms-vector unified-minterms-vector-1) >> >> (define (funct-unify-minterms-set-1-unit-future set1 set2) >> >> {function-unify-minterms-list <+ (λ (L) (apply >> function-unify-two-minterms-and-tag L))} >> >> ;; note : sorting is useless >> >> {minterms-set <+ (product-set-with-set-imperative-sorted set1 set2)} >> ;;(product-set-with-set-imperative set1 set2)} ;;(product-set-with-set set1 >> set2)} ;;(associate-set-with-set set1 set2)} ;; set multiplication : create >> list of pair of minterms >> >> {minterms-vector <- (list->vector minterms-set)} >> >> {minterms-vector-length <+ (vector-length minterms-vector)} >> >> {nb-procs <+ (current-processor-count)} >> >> {segmts <+ (segment 0 {minterms-vector-length - 1} nb-procs)} ;; >> compute the segments >> >> {unified-minterms-vector-1 <- (make-vector minterms-vector-length #f)} >> >> (run-in-parallel segmts proc-unify-minterms-seg) ;; run the parallel >> code >> >> {unified-minterms-set-1 <+ (vector->list unified-minterms-vector-1)} >> >> {unified-minterms-set-2 <+ (filter (λ (x) x) unified-minterms-set-1)} >> ;; remove #f results >> >> {unified-minterms-set <+ (remove-duplicates-sorted >> unified-minterms-set-2)} ;; uniq >> >> unified-minterms-set) >> >> i keeped your 'segment' definitions to index an array of data after >> convert it from list to vector (list->vector) which probably consume >> additional time on big data list ( i had more than 1000000 element list >> lengths at some point) >> >> i used a simplified version of run-in parallel (that do not do 'reduce >> after processing data): >> >> >> https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1794 >> >> the computation on a segment is done by those functions: >> >> >> https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1842 >> >> {function-unify-minterms-list <+ (λ (L) (apply >> function-unify-two-minterms-and-tag L))} >> >> ;; proc to be called with futures >> (define (proc-unify-minterms-seg seg) >> {start <+ (segment-start seg)} >> {end <+ (segment-end seg)} >> (for ({i <+ start} {i <= end} {i <- {i + 1}}) >> {mtL <+ {minterms-vector[i]}} >> {unified-minterms-vector-1[i] <- (function-unify-minterms-list >> mtL)})) >> >> >> i use those code in another program symbolically to compute a value named >> Cn: >> >> C0 = T >> C1 = T >> C2 = T >> C3 = (B1 ∨ B2) >> C4 = (B2 ∨ (B1 ∧ B3)) >> C5 = ((B1 ∧ B3) ∨ (B2 ∧ B3) ∨ (B2 ∧ B4) ∨ (B3 ∧ B4)) >> C6 = ((B1 ∧ B3 ∧ B5) ∨ (B2 ∧ B3 ∧ B5) ∨ (B2 ∧ B4) ∨ (B3 ∧ B4) ∨ (B4 ∧ B5)) >> C7 = ((B1 ∧ B3 ∧ B5) ∨ (B2 ∧ B3 ∧ B5) ∨ (B2 ∧ B4 ∧ B6) ∨ (B3 ∧ B4 ∧ B6) ∨ >> (B4 ∧ B5) ∨ (B5 ∧ B6)) >> C8 = ((B1 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B4 ∧ B6) ∨ (B3 ∧ >> B4 ∧ B6) ∨ (B4 ∧ B5 ∧ B7) ∨ (B5 ∧ B6) ∨ (B6 ∧ B7)) >> C9 = ((B1 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B3 ∧ B5 ∧ B7) ∨ (B2 ∧ B4 ∧ B6 ∧ B8) ∨ >> (B3 ∧ B4 ∧ B6 ∧ B8) ∨ (B4 ∧ B5 ∧ B7) ∨ (B5 ∧ B6 ∧ B8) ∨ (B6 ∧ B7) ∨ (B7 ∧ >> B8)) >> >> from C1 to C9 used to be fast,less than a minute for the whole with or >> without // >> >> C10 = ((B1 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B2 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B2 ∧ B4 ∧ >> B6 ∧ B8) ∨ (B3 ∧ B4 ∧ B6 ∧ B8) ∨ (B4 ∧ B5 ∧ B7 ∧ B9) ∨ (B5 ∧ B6 ∧ B8) ∨ (B6 >> ∧ B7 ∧ B9) ∨ (B7 ∧ B8) ∨ (B8 ∧ B9)) >> >> C10 takes a few minutes >> >> but C11 used to take one day before // with 'future' and i got now the >> result during less than one hour!!! >> >> C11 = ((B1 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B10 ∧ B2 ∧ B4 ∧ B6 ∧ B8) ∨ (B10 ∧ B3 ∧ >> B4 ∧ B6 ∧ B8) ∨ (B10 ∧ B5 ∧ B6 ∧ B8) ∨ (B10 ∧ B7 ∧ B8) ∨ (B10 ∧ B9) ∨ (B2 ∧ >> B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B4 ∧ B5 ∧ B7 ∧ B9) ∨ (B6 ∧ B7 ∧ B9) ∨ (B8 ∧ B9)) >> >> i never got C12 in the past ,even with 7 days of computation! and i got >> it today during the lunchbreak !!! >> >> C12 = ((B1 ∧ B11 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B10 ∧ B11) ∨ (B10 ∧ B2 ∧ B4 ∧ B6 >> ∧ B8) ∨ (B10 ∧ B3 ∧ B4 ∧ B6 ∧ B8) ∨ (B10 ∧ B5 ∧ B6 ∧ B8) ∨ (B10 ∧ B7 ∧ B8) >> ∨ (B10 ∧ B9) ∨ (B11 ∧ B2 ∧ B3 ∧ B5 ∧ B7 ∧ B9) ∨ (B11 ∧ B4 ∧ B5 ∧ B7 ∧ B9) ∨ >> (B11 ∧ B6 ∧ B7 ∧ B9) ∨ (B11 ∧ B8 ∧ B9)) >> >> (note that a wise people can find a general formula for Cn based on Cn-1 >> but that is another (mathematical) story....) >> >> i'm computing C13 but i see that it consumes 12gb out of 16gb of my >> system ! and stopped on the linux box : >> GC Warning: Repeated allocation of very large block (appr. size >> 510935040): >> May lead to memory leak and poor performance >> Processus arrêté >> but still running on the Mac laptop...ok will see that but i think that >> the data set is now huge and there is noting that can be done with that... >> >> note that there is still an hash table used in >> function-unify-two-minterms-and-tag and i will use another data structure >> and algo to avoid that, i feared that the concurrent access to hash table >> can cause the guile 'future' to crash or fails or to slow down the process >> but not! result is incredibly fast.Also i use continuation and i read it >> can cause problem with 'future' i will improve that too... >> >> I will see where i can improve the algo and data structure to optimize >> again but this is already really good. >> >> Thanks >> >> Damien >> >> >> On Fri, Oct 14, 2022 at 10:39 AM Zelphir Kaltstahl < >> zelphirkaltstahl@posteo.de> wrote: >> >>> Hello Damien, >>> On 10/14/22 10:21, Damien Mattei wrote: >>> >>> yes Zelphir i think there is a problem in the threading part of guile, >>> whatever the code is ,it run well the first time, and after is unstable. >>> Long ago at the very begin of Java language on my master project at >>> university i experienced same problem with Java "green" threads, under >>> windows and/or linux ,i can't remember. >>> >>> I'm trying your code and future, which have perheaps also the >>> portability with other schemes, future can provide "light" // , with >>> carefull code it could be ok. >>> >>> in your segment.scm code ,is segment-count possibly replaced by the >>> number of available CPUs or nodes, if i understand well? >>> >>> Regards, >>> Damien >>> >>> Correct. For each segment one future is used. >>> >>> However, there are scenarios, where one would rather want to interleave >>> the numbers of the whole range, to have a "fairer" workload per future, for >>> example: >>> >>> (1 2 3 4 5 6 7 8 9) >>> >>> -> (1 4 7), (2 5 8), (3 6 9) >>> >>> instead of >>> >>> -> (1 2 3) (4 5 6) (7 8 9) >>> >>> (I seem to remember this to be the case for Mandelbrot set calculations, >>> but might be wrong.) >>> >>> But that is all a matter of forming some segments and what a segment is, >>> not really part of the logic of creating futures. So one could create then >>> in any way that fits ones use-case. I have not generalized that segment >>> logic that far, but it is doable. >>> >>> Anyway, if anyone more knowledgeable could chime in on what the >>> performance differences between futures and parallel map are, that would be >>> great! Or pointing out some flaws that this kind of future usage might >>> have. Or when the point is reached to switch to guile-fibers library. >>> >>> Regards, >>> Zelphir >>> >>> -- >>> repositories: https://notabug.org/ZelphirKaltstahl >>> >>> [-- Attachment #2: Type: text/html, Size: 21674 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-12 21:29 ` Zelphir Kaltstahl 2022-10-14 8:21 ` Damien Mattei @ 2022-10-25 9:07 ` Mikael Djurfeldt 2022-10-25 9:11 ` Mikael Djurfeldt 1 sibling, 1 reply; 27+ messages in thread From: Mikael Djurfeldt @ 2022-10-25 9:07 UTC (permalink / raw) To: Zelphir Kaltstahl Cc: Damien Mattei, guile-user, guile-devel, Mikael Djurfeldt [-- Attachment #1: Type: text/plain, Size: 9302 bytes --] A piece of background on par-map: When I introduced par-map et al the only ambition was to have simple language constructs to invoke parallelism. The use case I had in mind was course grained parallelism where each piece of work is somewhat substantial. Back then, a thread was launched for each piece of work, however there was also a thread pool such that not all of the overhead of launching new threads always was required. Since then, par-map has been rewritten (by others) to be based on futures. (And now the thread pool is localized in the futures implementation---as "workers".) Looking in the code now, I think it is fair to say that it is still intended for coarse grained parallelism. There is some heavy lifting going on with mutexes and condition variables as well as shuffling around with list pairs. So, applying par-map on a huge list with small amount of work per item was never and still isn't the intended use case. It would of course be interesting if the code could be improved to support fine grained parallelism. :-) Best regards, Mikael On Wed, Oct 12, 2022 at 11:30 PM Zelphir Kaltstahl < zelphirkaltstahl@posteo.de> wrote: > Hi! > > On 10/12/22 22:27, Damien Mattei wrote: > > > https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1674 > > > > i commited the current version of code here with all files but it is > > huge.... :-/ > > > > On Wed, Oct 12, 2022 at 10:20 PM Damien Mattei <damien.mattei@gmail.com> > > wrote: > > > >> Mutex? i do not think code has situation where dead lock could happen, > it > >> is a code about minimalising logic expressions, it uses minterms , > minterms > >> set is a set of minterms :like this: > >> > >> example: > >> ((1 1 0) (1 1 1)) will be unified : (1 1 x) > >> because 0 and 1 are replaced by x > >> the minterms-set could have thousands of pair (mathematic not lisp) > >> minterms to unify > >> if there is more than one x as result there is no need to continue so i > >> escape with a continuation: > >> > >> minterms-set = > >> { > >> ((1 0 1 0) (1 1 1 0)) > >> ((1 0 1 0) (1 1 0 1)) > >> ((1 0 1 0) (1 0 1 1)) > >> ((1 0 1 0) (0 1 1 1)) > >> ((0 1 1 0) (1 1 1 0)) > >> ((0 1 1 0) (1 1 0 1)) > >> ((0 1 1 0) (1 0 1 1)) > >> ((0 1 1 0) (0 1 1 1)) > >> ((0 1 0 1) (1 1 1 0)) > >> ((0 1 0 1) (1 1 0 1)) > >> ((0 1 0 1) (1 0 1 1)) > >> ((0 1 0 1) (0 1 1 1)) > >> ((0 0 1 1) (1 1 1 0)) > >> ((0 0 1 1) (1 1 0 1)) > >> ((0 0 1 1) (1 0 1 1)) > >> ((0 0 1 1) (0 1 1 1)) > >> } > >> > >> replace { } by () to have the list, other example at another level : > >> > >> minterms-set = > >> { > >> ((0 x 1 1) (x 1 1 1)) > >> ((0 x 1 1) (1 x 1 1)) > >> ((0 x 1 1) (1 1 x 1)) > >> ((0 x 1 1) (1 1 1 x)) > >> ((x 0 1 1) (x 1 1 1)) > >> ((x 0 1 1) (1 x 1 1)) > >> ((x 0 1 1) (1 1 x 1)) > >> ((x 0 1 1) (1 1 1 x)) > >> ((0 1 x 1) (x 1 1 1)) > >> ((0 1 x 1) (1 x 1 1)) > >> ((0 1 x 1) (1 1 x 1)) > >> ((0 1 x 1) (1 1 1 x)) > >> ((x 1 0 1) (x 1 1 1)) > >> ((x 1 0 1) (1 x 1 1)) > >> ((x 1 0 1) (1 1 x 1)) > >> ((x 1 0 1) (1 1 1 x)) > >> ((0 1 1 x) (x 1 1 1)) > >> ((0 1 1 x) (1 x 1 1)) > >> ((0 1 1 x) (1 1 x 1)) > >> ((0 1 1 x) (1 1 1 x)) > >> ((x 1 1 0) (x 1 1 1)) > >> ((x 1 1 0) (1 x 1 1)) > >> ((x 1 1 0) (1 1 x 1)) > >> ((x 1 1 0) (1 1 1 x)) > >> ((1 0 1 x) (x 1 1 1)) > >> ((1 0 1 x) (1 x 1 1)) > >> ((1 0 1 x) (1 1 x 1)) > >> ((1 0 1 x) (1 1 1 x)) > >> ((1 x 1 0) (x 1 1 1)) > >> ((1 x 1 0) (1 x 1 1)) > >> ((1 x 1 0) (1 1 x 1)) > >> ((1 x 1 0) (1 1 1 x)) > >> } > >> > >> here we see some minterms are already unified > >> > >> it is not easy to read even by me because i wrote the code many years > ago > >> and is split in many files, but here it is: > >> > >> (par-map function-unify-minterms-list minterms-set) > >> > >> {function-unify-minterms-list <+ (λ (L) (apply > >> function-unify-two-minterms-and-tag L))} > >> > >> (define (unify-two-minterms mt1 mt2) > >> (function-map-with-escaping-by-kontinuation2 > >> (macro-function-compare-2-bits-with-continuation) mt1 mt2)) > >> > >> ;; (function-map-with-escaping-by-kontinuation2 > >> (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 0) > '(1 > >> 1 0 1 1 1 1 1)) > >> > >> ;; list1 = (1 1 0 1 0 1 1 0) > >> ;; more-lists = ((1 1 0 1 1 1 1 1)) > >> ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 1)) > >> ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> > >> > >> ;; #f > >> ;; > >> ;; (function-map-with-escaping-by-kontinuation2 > >> (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 0) > '(1 > >> 1 0 1 1 1 1 0)) > >> > >> ;; list1 = (1 1 0 1 0 1 1 0) > >> ;; more-lists = ((1 1 0 1 1 1 1 0)) > >> ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 0)) > >> ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> > >> > >> ;; '(1 1 0 1 x 1 1 0) > >> (define (function-map-with-escaping-by-kontinuation2 clozure list1 . > >> more-lists) > >> (call/cc (lambda (kontinuation) > >> (let ((lists (cons list1 more-lists)) > >> (funct-continu ;; this function have the kontinuation in his > environment > >> (lambda (arg1 . more-args) > >> (let ((args (cons arg1 more-args))) > >> (apply clozure kontinuation args))))) ;; a tester: (apply clozure (cons > >> conti args)) > >> > >> ;; (newline) > >> ;; (dv list1) > >> ;; (dv more-lists) > >> ;; (dv lists) > >> ;; (dv clozure) > >> ;; (newline) > >> > >> (apply map funct-continu lists))))) > >> > >> (define-syntax macro-function-compare-2-bits-with-continuation ;; > >> continuation version of macro-compare-2-bits > >> ;; i need a macro because of external function to the clozure > >> (syntax-rules () > >> ((_) (let ((cnt 0)) ;; counter > >> (lambda (continuation b1 b2) (if (equal? b1 b2) > >> b1 > >> (begin > >> (set! cnt (add1 cnt)) ;; we leave with continuation in case cpt > > 1, we > >> can have used a flag too instead of a counter > >> (when (> cnt 1) (continuation #f)) ;; escaping with the continuation > >> 'x))))))) ;; return x in case of (b1,b2) = (O,1) or (1,0) > >> > >> what could have caused mutex if in the latter definition above (let > ((cnt > >> 0)) ;; counter was defined at top level and shared by all threads!!! yes > >> there could have be some mutex but this is not the case, i think even > all > >> function are pure so why is it more slow with // than without? > >> Damien > >> > >> On Wed, Oct 12, 2022 at 8:45 PM Maxime Devos <maximedevos@telenet.be> > >> wrote: > >> > >>> On 12-10-2022 19:19, Damien Mattei wrote: > >>>> Hello, > >>>> all is in the title, i test on a approximately 30000 element list , i > >>> got > >>>> 9s with map and 3min 30s with par-map on exactly the same piece of > >>> code!? > >>> > [...] > >>> > > >>>> translated from Scheme+ to Scheme: > >>>> (define unified-minterms-set-1 (map function-unify-minterms-list > >>>> minterms-set)) ;;(par-map function-unify-minterms-list minterms-set)) > >>> The definition of 'function-unify-minterms-list' and 'minterms-set' is > >>> missing. Without a test case, we can only speculate what's going on. > >>> (E.g., maybe it grabs a mutex). > >>> > >>> Greetings, > >>> Maxime. > I don't want to scare anyone, just maybe warn about parallel map. I once > tried > to use Guile's parallel map function for a decision tree implementation > ( > https://notabug.org/ZelphirKaltstahl/guile-ml/src/cf666801fea91c9fa8fa290764ff6c60b7f3949d/decision-tree.scm), > > where each branch while learning the tree would call parallel map again > for sub > branches and so on. Somehow it made Guile crash (I don't have the error > message > any longer, but I did post about it on the mailing list back then.). I > never > figured out, what went wrong. All I had was pure function calls and math > inside > the thing that parallel map was supposed to run. > > Ultimately I simply tried other parallelism constructs and when I switched > to > using futures instead, everything worked fine, no crashes, no errors. > > Since that time, I did not use parallel map and instead used futures. > Recently I > made a parallelization thing for solving exercises of Project Euler using > multiple cores, so that some solutions are calculated faster. Maybe this > can > help or can be adapted to another use case: > > > https://notabug.org/ZelphirKaltstahl/guile-project-euler-solutions/src/ebb19b11b465903105924adb6252f1e2ecf63859/lib/parallelism.scm#L11-L30 > > It expects ranges of things, which are called `segments` in the code. > Usually > ranges of numbers for Project Euler things. Here is the code to split a > range > into segments: > > > https://notabug.org/ZelphirKaltstahl/guile-project-euler-solutions/src/ebb19b11b465903105924adb6252f1e2ecf63859/lib/segment.scm > > (Check any solution using it for an example.) > > So this might be a bit too specific for general parallel things, but I > guess one > could change the way futures are used in `run-in-parallel`, to fit any > other > purpose. > > Best regards, > Zelphir > > -- > repositories: https://notabug.org/ZelphirKaltstahl > > > [-- Attachment #2: Type: text/html, Size: 12202 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-25 9:07 ` Mikael Djurfeldt @ 2022-10-25 9:11 ` Mikael Djurfeldt 2022-10-25 14:09 ` Damien Mattei 0 siblings, 1 reply; 27+ messages in thread From: Mikael Djurfeldt @ 2022-10-25 9:11 UTC (permalink / raw) To: Zelphir Kaltstahl; +Cc: Damien Mattei, guile-user, guile-devel [-- Attachment #1: Type: text/plain, Size: 9889 bytes --] Also, I would believe that any crashes in this context are neither due to the futures implementation nor par-map et al. I would think that crashes are due to the Guile basic thread support itself. On Tue, Oct 25, 2022 at 11:07 AM Mikael Djurfeldt <mikael@djurfeldt.com> wrote: > A piece of background on par-map: > > When I introduced par-map et al the only ambition was to have simple > language constructs to invoke parallelism. The use case I had in mind was > course grained parallelism where each piece of work is somewhat > substantial. Back then, a thread was launched for each piece of work, > however there was also a thread pool such that not all of the overhead of > launching new threads always was required. > > Since then, par-map has been rewritten (by others) to be based on futures. > (And now the thread pool is localized in the futures implementation---as > "workers".) Looking in the code now, I think it is fair to say that it is > still intended for coarse grained parallelism. There is some heavy lifting > going on with mutexes and condition variables as well as shuffling around > with list pairs. > > So, applying par-map on a huge list with small amount of work per item was > never and still isn't the intended use case. > > It would of course be interesting if the code could be improved to support > fine grained parallelism. :-) > > Best regards, > Mikael > > On Wed, Oct 12, 2022 at 11:30 PM Zelphir Kaltstahl < > zelphirkaltstahl@posteo.de> wrote: > >> Hi! >> >> On 10/12/22 22:27, Damien Mattei wrote: >> > >> https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1674 >> > >> > i commited the current version of code here with all files but it is >> > huge.... :-/ >> > >> > On Wed, Oct 12, 2022 at 10:20 PM Damien Mattei <damien.mattei@gmail.com >> > >> > wrote: >> > >> >> Mutex? i do not think code has situation where dead lock could happen, >> it >> >> is a code about minimalising logic expressions, it uses minterms , >> minterms >> >> set is a set of minterms :like this: >> >> >> >> example: >> >> ((1 1 0) (1 1 1)) will be unified : (1 1 x) >> >> because 0 and 1 are replaced by x >> >> the minterms-set could have thousands of pair (mathematic not lisp) >> >> minterms to unify >> >> if there is more than one x as result there is no need to continue so i >> >> escape with a continuation: >> >> >> >> minterms-set = >> >> { >> >> ((1 0 1 0) (1 1 1 0)) >> >> ((1 0 1 0) (1 1 0 1)) >> >> ((1 0 1 0) (1 0 1 1)) >> >> ((1 0 1 0) (0 1 1 1)) >> >> ((0 1 1 0) (1 1 1 0)) >> >> ((0 1 1 0) (1 1 0 1)) >> >> ((0 1 1 0) (1 0 1 1)) >> >> ((0 1 1 0) (0 1 1 1)) >> >> ((0 1 0 1) (1 1 1 0)) >> >> ((0 1 0 1) (1 1 0 1)) >> >> ((0 1 0 1) (1 0 1 1)) >> >> ((0 1 0 1) (0 1 1 1)) >> >> ((0 0 1 1) (1 1 1 0)) >> >> ((0 0 1 1) (1 1 0 1)) >> >> ((0 0 1 1) (1 0 1 1)) >> >> ((0 0 1 1) (0 1 1 1)) >> >> } >> >> >> >> replace { } by () to have the list, other example at another level : >> >> >> >> minterms-set = >> >> { >> >> ((0 x 1 1) (x 1 1 1)) >> >> ((0 x 1 1) (1 x 1 1)) >> >> ((0 x 1 1) (1 1 x 1)) >> >> ((0 x 1 1) (1 1 1 x)) >> >> ((x 0 1 1) (x 1 1 1)) >> >> ((x 0 1 1) (1 x 1 1)) >> >> ((x 0 1 1) (1 1 x 1)) >> >> ((x 0 1 1) (1 1 1 x)) >> >> ((0 1 x 1) (x 1 1 1)) >> >> ((0 1 x 1) (1 x 1 1)) >> >> ((0 1 x 1) (1 1 x 1)) >> >> ((0 1 x 1) (1 1 1 x)) >> >> ((x 1 0 1) (x 1 1 1)) >> >> ((x 1 0 1) (1 x 1 1)) >> >> ((x 1 0 1) (1 1 x 1)) >> >> ((x 1 0 1) (1 1 1 x)) >> >> ((0 1 1 x) (x 1 1 1)) >> >> ((0 1 1 x) (1 x 1 1)) >> >> ((0 1 1 x) (1 1 x 1)) >> >> ((0 1 1 x) (1 1 1 x)) >> >> ((x 1 1 0) (x 1 1 1)) >> >> ((x 1 1 0) (1 x 1 1)) >> >> ((x 1 1 0) (1 1 x 1)) >> >> ((x 1 1 0) (1 1 1 x)) >> >> ((1 0 1 x) (x 1 1 1)) >> >> ((1 0 1 x) (1 x 1 1)) >> >> ((1 0 1 x) (1 1 x 1)) >> >> ((1 0 1 x) (1 1 1 x)) >> >> ((1 x 1 0) (x 1 1 1)) >> >> ((1 x 1 0) (1 x 1 1)) >> >> ((1 x 1 0) (1 1 x 1)) >> >> ((1 x 1 0) (1 1 1 x)) >> >> } >> >> >> >> here we see some minterms are already unified >> >> >> >> it is not easy to read even by me because i wrote the code many >> years ago >> >> and is split in many files, but here it is: >> >> >> >> (par-map function-unify-minterms-list minterms-set) >> >> >> >> {function-unify-minterms-list <+ (λ (L) (apply >> >> function-unify-two-minterms-and-tag L))} >> >> >> >> (define (unify-two-minterms mt1 mt2) >> >> (function-map-with-escaping-by-kontinuation2 >> >> (macro-function-compare-2-bits-with-continuation) mt1 mt2)) >> >> >> >> ;; (function-map-with-escaping-by-kontinuation2 >> >> (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 0) >> '(1 >> >> 1 0 1 1 1 1 1)) >> >> >> >> ;; list1 = (1 1 0 1 0 1 1 0) >> >> ;; more-lists = ((1 1 0 1 1 1 1 1)) >> >> ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 1)) >> >> ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> >> >> >> >> ;; #f >> >> ;; >> >> ;; (function-map-with-escaping-by-kontinuation2 >> >> (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 >> 0) '(1 >> >> 1 0 1 1 1 1 0)) >> >> >> >> ;; list1 = (1 1 0 1 0 1 1 0) >> >> ;; more-lists = ((1 1 0 1 1 1 1 0)) >> >> ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 0)) >> >> ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> >> >> >> >> ;; '(1 1 0 1 x 1 1 0) >> >> (define (function-map-with-escaping-by-kontinuation2 clozure list1 . >> >> more-lists) >> >> (call/cc (lambda (kontinuation) >> >> (let ((lists (cons list1 more-lists)) >> >> (funct-continu ;; this function have the kontinuation in his >> environment >> >> (lambda (arg1 . more-args) >> >> (let ((args (cons arg1 more-args))) >> >> (apply clozure kontinuation args))))) ;; a tester: (apply clozure (cons >> >> conti args)) >> >> >> >> ;; (newline) >> >> ;; (dv list1) >> >> ;; (dv more-lists) >> >> ;; (dv lists) >> >> ;; (dv clozure) >> >> ;; (newline) >> >> >> >> (apply map funct-continu lists))))) >> >> >> >> (define-syntax macro-function-compare-2-bits-with-continuation ;; >> >> continuation version of macro-compare-2-bits >> >> ;; i need a macro because of external function to the clozure >> >> (syntax-rules () >> >> ((_) (let ((cnt 0)) ;; counter >> >> (lambda (continuation b1 b2) (if (equal? b1 b2) >> >> b1 >> >> (begin >> >> (set! cnt (add1 cnt)) ;; we leave with continuation in case cpt > >> 1, we >> >> can have used a flag too instead of a counter >> >> (when (> cnt 1) (continuation #f)) ;; escaping with the >> continuation >> >> 'x))))))) ;; return x in case of (b1,b2) = (O,1) or (1,0) >> >> >> >> what could have caused mutex if in the latter definition above (let >> ((cnt >> >> 0)) ;; counter was defined at top level and shared by all threads!!! >> yes >> >> there could have be some mutex but this is not the case, i think even >> all >> >> function are pure so why is it more slow with // than without? >> >> Damien >> >> >> >> On Wed, Oct 12, 2022 at 8:45 PM Maxime Devos <maximedevos@telenet.be> >> >> wrote: >> >> >> >>> On 12-10-2022 19:19, Damien Mattei wrote: >> >>>> Hello, >> >>>> all is in the title, i test on a approximately 30000 element list , i >> >>> got >> >>>> 9s with map and 3min 30s with par-map on exactly the same piece of >> >>> code!? >> >>> > [...] >> >>> > >> >>>> translated from Scheme+ to Scheme: >> >>>> (define unified-minterms-set-1 (map function-unify-minterms-list >> >>>> minterms-set)) ;;(par-map function-unify-minterms-list minterms-set)) >> >>> The definition of 'function-unify-minterms-list' and 'minterms-set' is >> >>> missing. Without a test case, we can only speculate what's going on. >> >>> (E.g., maybe it grabs a mutex). >> >>> >> >>> Greetings, >> >>> Maxime. >> I don't want to scare anyone, just maybe warn about parallel map. I once >> tried >> to use Guile's parallel map function for a decision tree implementation >> ( >> https://notabug.org/ZelphirKaltstahl/guile-ml/src/cf666801fea91c9fa8fa290764ff6c60b7f3949d/decision-tree.scm), >> >> where each branch while learning the tree would call parallel map again >> for sub >> branches and so on. Somehow it made Guile crash (I don't have the error >> message >> any longer, but I did post about it on the mailing list back then.). I >> never >> figured out, what went wrong. All I had was pure function calls and math >> inside >> the thing that parallel map was supposed to run. >> >> Ultimately I simply tried other parallelism constructs and when I >> switched to >> using futures instead, everything worked fine, no crashes, no errors. >> >> Since that time, I did not use parallel map and instead used futures. >> Recently I >> made a parallelization thing for solving exercises of Project Euler using >> multiple cores, so that some solutions are calculated faster. Maybe this >> can >> help or can be adapted to another use case: >> >> >> https://notabug.org/ZelphirKaltstahl/guile-project-euler-solutions/src/ebb19b11b465903105924adb6252f1e2ecf63859/lib/parallelism.scm#L11-L30 >> >> It expects ranges of things, which are called `segments` in the code. >> Usually >> ranges of numbers for Project Euler things. Here is the code to split a >> range >> into segments: >> >> >> https://notabug.org/ZelphirKaltstahl/guile-project-euler-solutions/src/ebb19b11b465903105924adb6252f1e2ecf63859/lib/segment.scm >> >> (Check any solution using it for an example.) >> >> So this might be a bit too specific for general parallel things, but I >> guess one >> could change the way futures are used in `run-in-parallel`, to fit any >> other >> purpose. >> >> Best regards, >> Zelphir >> >> -- >> repositories: https://notabug.org/ZelphirKaltstahl >> >> >> [-- Attachment #2: Type: text/html, Size: 12781 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-25 9:11 ` Mikael Djurfeldt @ 2022-10-25 14:09 ` Damien Mattei 0 siblings, 0 replies; 27+ messages in thread From: Damien Mattei @ 2022-10-25 14:09 UTC (permalink / raw) To: mikael; +Cc: Zelphir Kaltstahl, guile-user, guile-devel [-- Attachment #1: Type: text/plain, Size: 12643 bytes --] Hello Mikael, your message comes very well because i decided yesterday,partly due to the discussion in mailing list, to review all the // method used in my code and to use them to perform benchmark to see which one is preferable to use with the algorithmic problem of putting a logic expression in its canonical minimal disjunctive or conjunctive form. I used 4 methods: -sequential (map with no //) -par-map (//) -threads (//) -futures (//) But, of course, the data structure is not the same now, it will be lists with sequential and par-map and vectors with threads and futures, as i already experimented problems (blocking, crashing,false results) with some (threads,futures) . Also i have solved the concurrent access problem to the hash table with lists or vectors depending if i use map or par-map or futures and threads, but the algorithm remains the same in all case. I computed from C1,C2,C3 ... to C12 (i do not write the logical expressions here, some peoples seeing those infix mathematical expression coming in the mailing list as drones in the peaceful sky of the lambda calculus expressions ;-) ) but here is the results: map: 10' 17" for C12 (5" for C10) par-map: 1'21" for C10, more than 2h 40' for C12 threads: blocks randomly before C7 (works but is not reentrant, perheaps a problem in the code i use with thread programming) futures:8" for C12, 25" for C13,2' for C14,7' for C15... the best performance are,from far, with futures and the code provided by Zelphir. on a 6 cores processor with 16Gb of memory.note at C15 computation the memory containing minterms and logical expression not simplified is about 3 Gb: PID UTIL. PR NI VIRT RES SHR S %CPU %MEM TEMPS+ COM. 61051 mattei 20 0 *3339388* 2,7g 22368 R 463,1 *17,2 * 33:27.92 *guile* cf : https://en.wikipedia.org/wiki/Quine%E2%80%93McCluskey_algorithm#Complexity what i will do is write a Python version of the computation of Cn that uses the Sympy minimal disjunctive normal form procedure of the Sympy library , first to check my scheme code result and perheaps compare the speed, i know python is slow but as it is a library (compiled? but written in python as far as i know?), well, i'm a bit nervous to compare the speed between Python and Scheme... Best regards, Damien On Tue, Oct 25, 2022 at 11:11 AM Mikael Djurfeldt <mikael@djurfeldt.com> wrote: > Also, I would believe that any crashes in this context are neither due to > the futures implementation nor par-map et al. I would think that crashes > are due to the Guile basic thread support itself. > > On Tue, Oct 25, 2022 at 11:07 AM Mikael Djurfeldt <mikael@djurfeldt.com> > wrote: > >> A piece of background on par-map: >> >> When I introduced par-map et al the only ambition was to have simple >> language constructs to invoke parallelism. The use case I had in mind was >> course grained parallelism where each piece of work is somewhat >> substantial. Back then, a thread was launched for each piece of work, >> however there was also a thread pool such that not all of the overhead of >> launching new threads always was required. >> >> Since then, par-map has been rewritten (by others) to be based on >> futures. (And now the thread pool is localized in the futures >> implementation---as "workers".) Looking in the code now, I think it is fair >> to say that it is still intended for coarse grained parallelism. There is >> some heavy lifting going on with mutexes and condition variables as well as >> shuffling around with list pairs. >> >> So, applying par-map on a huge list with small amount of work per item >> was never and still isn't the intended use case. >> >> It would of course be interesting if the code could be improved to >> support fine grained parallelism. :-) >> >> Best regards, >> Mikael >> >> On Wed, Oct 12, 2022 at 11:30 PM Zelphir Kaltstahl < >> zelphirkaltstahl@posteo.de> wrote: >> >>> Hi! >>> >>> On 10/12/22 22:27, Damien Mattei wrote: >>> > >>> https://github.com/damien-mattei/library-FunctProg/blob/master/guile/logiki%2B.scm#L1674 >>> > >>> > i commited the current version of code here with all files but it is >>> > huge.... :-/ >>> > >>> > On Wed, Oct 12, 2022 at 10:20 PM Damien Mattei < >>> damien.mattei@gmail.com> >>> > wrote: >>> > >>> >> Mutex? i do not think code has situation where dead lock could >>> happen, it >>> >> is a code about minimalising logic expressions, it uses minterms , >>> minterms >>> >> set is a set of minterms :like this: >>> >> >>> >> example: >>> >> ((1 1 0) (1 1 1)) will be unified : (1 1 x) >>> >> because 0 and 1 are replaced by x >>> >> the minterms-set could have thousands of pair (mathematic not lisp) >>> >> minterms to unify >>> >> if there is more than one x as result there is no need to continue so >>> i >>> >> escape with a continuation: >>> >> >>> >> minterms-set = >>> >> { >>> >> ((1 0 1 0) (1 1 1 0)) >>> >> ((1 0 1 0) (1 1 0 1)) >>> >> ((1 0 1 0) (1 0 1 1)) >>> >> ((1 0 1 0) (0 1 1 1)) >>> >> ((0 1 1 0) (1 1 1 0)) >>> >> ((0 1 1 0) (1 1 0 1)) >>> >> ((0 1 1 0) (1 0 1 1)) >>> >> ((0 1 1 0) (0 1 1 1)) >>> >> ((0 1 0 1) (1 1 1 0)) >>> >> ((0 1 0 1) (1 1 0 1)) >>> >> ((0 1 0 1) (1 0 1 1)) >>> >> ((0 1 0 1) (0 1 1 1)) >>> >> ((0 0 1 1) (1 1 1 0)) >>> >> ((0 0 1 1) (1 1 0 1)) >>> >> ((0 0 1 1) (1 0 1 1)) >>> >> ((0 0 1 1) (0 1 1 1)) >>> >> } >>> >> >>> >> replace { } by () to have the list, other example at another level : >>> >> >>> >> minterms-set = >>> >> { >>> >> ((0 x 1 1) (x 1 1 1)) >>> >> ((0 x 1 1) (1 x 1 1)) >>> >> ((0 x 1 1) (1 1 x 1)) >>> >> ((0 x 1 1) (1 1 1 x)) >>> >> ((x 0 1 1) (x 1 1 1)) >>> >> ((x 0 1 1) (1 x 1 1)) >>> >> ((x 0 1 1) (1 1 x 1)) >>> >> ((x 0 1 1) (1 1 1 x)) >>> >> ((0 1 x 1) (x 1 1 1)) >>> >> ((0 1 x 1) (1 x 1 1)) >>> >> ((0 1 x 1) (1 1 x 1)) >>> >> ((0 1 x 1) (1 1 1 x)) >>> >> ((x 1 0 1) (x 1 1 1)) >>> >> ((x 1 0 1) (1 x 1 1)) >>> >> ((x 1 0 1) (1 1 x 1)) >>> >> ((x 1 0 1) (1 1 1 x)) >>> >> ((0 1 1 x) (x 1 1 1)) >>> >> ((0 1 1 x) (1 x 1 1)) >>> >> ((0 1 1 x) (1 1 x 1)) >>> >> ((0 1 1 x) (1 1 1 x)) >>> >> ((x 1 1 0) (x 1 1 1)) >>> >> ((x 1 1 0) (1 x 1 1)) >>> >> ((x 1 1 0) (1 1 x 1)) >>> >> ((x 1 1 0) (1 1 1 x)) >>> >> ((1 0 1 x) (x 1 1 1)) >>> >> ((1 0 1 x) (1 x 1 1)) >>> >> ((1 0 1 x) (1 1 x 1)) >>> >> ((1 0 1 x) (1 1 1 x)) >>> >> ((1 x 1 0) (x 1 1 1)) >>> >> ((1 x 1 0) (1 x 1 1)) >>> >> ((1 x 1 0) (1 1 x 1)) >>> >> ((1 x 1 0) (1 1 1 x)) >>> >> } >>> >> >>> >> here we see some minterms are already unified >>> >> >>> >> it is not easy to read even by me because i wrote the code many >>> years ago >>> >> and is split in many files, but here it is: >>> >> >>> >> (par-map function-unify-minterms-list minterms-set) >>> >> >>> >> {function-unify-minterms-list <+ (λ (L) (apply >>> >> function-unify-two-minterms-and-tag L))} >>> >> >>> >> (define (unify-two-minterms mt1 mt2) >>> >> (function-map-with-escaping-by-kontinuation2 >>> >> (macro-function-compare-2-bits-with-continuation) mt1 mt2)) >>> >> >>> >> ;; (function-map-with-escaping-by-kontinuation2 >>> >> (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 >>> 0) '(1 >>> >> 1 0 1 1 1 1 1)) >>> >> >>> >> ;; list1 = (1 1 0 1 0 1 1 0) >>> >> ;; more-lists = ((1 1 0 1 1 1 1 1)) >>> >> ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 1)) >>> >> ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> >>> >> >>> >> ;; #f >>> >> ;; >>> >> ;; (function-map-with-escaping-by-kontinuation2 >>> >> (macro-function-compare-2-bits-with-continuation) '(1 1 0 1 0 1 1 >>> 0) '(1 >>> >> 1 0 1 1 1 1 0)) >>> >> >>> >> ;; list1 = (1 1 0 1 0 1 1 0) >>> >> ;; more-lists = ((1 1 0 1 1 1 1 0)) >>> >> ;; lists = ((1 1 0 1 0 1 1 0) (1 1 0 1 1 1 1 0)) >>> >> ;; clozure = #<procedure:...gos-DrRacket.scm:195:11> >>> >> >>> >> ;; '(1 1 0 1 x 1 1 0) >>> >> (define (function-map-with-escaping-by-kontinuation2 clozure list1 . >>> >> more-lists) >>> >> (call/cc (lambda (kontinuation) >>> >> (let ((lists (cons list1 more-lists)) >>> >> (funct-continu ;; this function have the kontinuation in his >>> environment >>> >> (lambda (arg1 . more-args) >>> >> (let ((args (cons arg1 more-args))) >>> >> (apply clozure kontinuation args))))) ;; a tester: (apply clozure >>> (cons >>> >> conti args)) >>> >> >>> >> ;; (newline) >>> >> ;; (dv list1) >>> >> ;; (dv more-lists) >>> >> ;; (dv lists) >>> >> ;; (dv clozure) >>> >> ;; (newline) >>> >> >>> >> (apply map funct-continu lists))))) >>> >> >>> >> (define-syntax macro-function-compare-2-bits-with-continuation ;; >>> >> continuation version of macro-compare-2-bits >>> >> ;; i need a macro because of external function to the clozure >>> >> (syntax-rules () >>> >> ((_) (let ((cnt 0)) ;; counter >>> >> (lambda (continuation b1 b2) (if (equal? b1 b2) >>> >> b1 >>> >> (begin >>> >> (set! cnt (add1 cnt)) ;; we leave with continuation in case cpt > >>> 1, we >>> >> can have used a flag too instead of a counter >>> >> (when (> cnt 1) (continuation #f)) ;; escaping with the >>> continuation >>> >> 'x))))))) ;; return x in case of (b1,b2) = (O,1) or (1,0) >>> >> >>> >> what could have caused mutex if in the latter definition above (let >>> ((cnt >>> >> 0)) ;; counter was defined at top level and shared by all threads!!! >>> yes >>> >> there could have be some mutex but this is not the case, i think >>> even all >>> >> function are pure so why is it more slow with // than without? >>> >> Damien >>> >> >>> >> On Wed, Oct 12, 2022 at 8:45 PM Maxime Devos <maximedevos@telenet.be> >>> >> wrote: >>> >> >>> >>> On 12-10-2022 19:19, Damien Mattei wrote: >>> >>>> Hello, >>> >>>> all is in the title, i test on a approximately 30000 element list , >>> i >>> >>> got >>> >>>> 9s with map and 3min 30s with par-map on exactly the same piece of >>> >>> code!? >>> >>> > [...] >>> >>> > >>> >>>> translated from Scheme+ to Scheme: >>> >>>> (define unified-minterms-set-1 (map function-unify-minterms-list >>> >>>> minterms-set)) ;;(par-map function-unify-minterms-list >>> minterms-set)) >>> >>> The definition of 'function-unify-minterms-list' and 'minterms-set' >>> is >>> >>> missing. Without a test case, we can only speculate what's going on. >>> >>> (E.g., maybe it grabs a mutex). >>> >>> >>> >>> Greetings, >>> >>> Maxime. >>> I don't want to scare anyone, just maybe warn about parallel map. I once >>> tried >>> to use Guile's parallel map function for a decision tree implementation >>> ( >>> https://notabug.org/ZelphirKaltstahl/guile-ml/src/cf666801fea91c9fa8fa290764ff6c60b7f3949d/decision-tree.scm), >>> >>> where each branch while learning the tree would call parallel map again >>> for sub >>> branches and so on. Somehow it made Guile crash (I don't have the error >>> message >>> any longer, but I did post about it on the mailing list back then.). I >>> never >>> figured out, what went wrong. All I had was pure function calls and math >>> inside >>> the thing that parallel map was supposed to run. >>> >>> Ultimately I simply tried other parallelism constructs and when I >>> switched to >>> using futures instead, everything worked fine, no crashes, no errors. >>> >>> Since that time, I did not use parallel map and instead used futures. >>> Recently I >>> made a parallelization thing for solving exercises of Project Euler >>> using >>> multiple cores, so that some solutions are calculated faster. Maybe this >>> can >>> help or can be adapted to another use case: >>> >>> >>> https://notabug.org/ZelphirKaltstahl/guile-project-euler-solutions/src/ebb19b11b465903105924adb6252f1e2ecf63859/lib/parallelism.scm#L11-L30 >>> >>> It expects ranges of things, which are called `segments` in the code. >>> Usually >>> ranges of numbers for Project Euler things. Here is the code to split a >>> range >>> into segments: >>> >>> >>> https://notabug.org/ZelphirKaltstahl/guile-project-euler-solutions/src/ebb19b11b465903105924adb6252f1e2ecf63859/lib/segment.scm >>> >>> (Check any solution using it for an example.) >>> >>> So this might be a bit too specific for general parallel things, but I >>> guess one >>> could change the way futures are used in `run-in-parallel`, to fit any >>> other >>> purpose. >>> >>> Best regards, >>> Zelphir >>> >>> -- >>> repositories: https://notabug.org/ZelphirKaltstahl >>> >>> >>> [-- Attachment #2: Type: text/html, Size: 17537 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-12 20:20 ` Damien Mattei 2022-10-12 20:27 ` Damien Mattei @ 2022-10-12 21:44 ` Maxime Devos 1 sibling, 0 replies; 27+ messages in thread From: Maxime Devos @ 2022-10-12 21:44 UTC (permalink / raw) To: Damien Mattei; +Cc: guile-user, guile-devel [-- Attachment #1.1.1: Type: text/plain, Size: 1040 bytes --] On 12-10-2022 22:20, Damien Mattei wrote: > Mutex? i do not think code has situation where dead lock could happen, > it is a code about minimalising logic expressions, it uses minterms , > minterms set is a set of minterms :like this: I didn't mean deadlocks, I just meant a single mutex being taken by all the threads. Also, you seem to have a global hash table on line 1603 -- presumably there's a mutex in there (and even if not, likely there are CPU cache issues). > [...] I propose to minimise this complicated test case (doesn't need to be equivalent, just needs to demonstrate the 'map-par slower than map') and to change it to standard-ish Scheme instead of your Scheme+ variant. > On Wed, Oct 12, 2022 at 8:45 PM Maxime Devos <maximedevos@telenet.be > <mailto:maximedevos@telenet.be>> wrote: > > [rest of copied previous message, without any comments] This is top-posting. For why not to top-post, https://wiki.lyx.org/FAQ/ListNetiquette has various information. Greetings, Maxime. [-- Attachment #1.1.2: OpenPGP public key --] [-- Type: application/pgp-keys, Size: 929 bytes --] [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 236 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-12 17:19 map-par slower than map Damien Mattei 2022-10-12 18:45 ` Maxime Devos @ 2022-10-12 21:55 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 2022-10-13 7:40 ` Damien Mattei 2022-10-13 10:44 ` Damien Mattei 1 sibling, 2 replies; 27+ messages in thread From: Olivier Dion via Developers list for Guile, the GNU extensibility library @ 2022-10-12 21:55 UTC (permalink / raw) To: Damien Mattei, guile-user, guile-devel On Wed, 12 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: > Hello, > all is in the title, i test on a approximately 30000 element list , i got > 9s with map and 3min 30s with par-map on exactly the same piece of > code!? I can only speculate here. But trying with a very simple example here: --8<---------------cut here---------------start------------->8--- (use-modules (statprof)) (statprof (lambda () (par-map 1+ (iota 300000)))) --8<---------------cut here---------------end--------------->8--- Performance are terrible. I don't know how par-map is implemented, but if it does 1 element static scheduling -- which it probably does because you pass a linked list and not a vector -- then yeah you can assure that thing will be very slow. You're probably better off with dynamic scheduling with vectors. Here's a quick snippet I made for static scheduling but with vectors. Feel free to roll your own. --8<---------------cut here---------------start------------->8--- (use-modules (srfi srfi-1) (ice-9 threads)) (define* (par-map-vector proc input #:optional (max-thread (current-processor-count))) (let* ((block-size (quotient (vector-length input) max-thread)) (rest (remainder (vector-length input) max-thread)) (output (make-vector (vector-length input) #f))) (when (not (zero? block-size)) (let ((mtx (make-mutex)) (cnd (make-condition-variable)) (n 0)) (fold (lambda (scale output) (begin-thread (let lp ((i 0)) (when (< i block-size) (let ((i (+ i (* scale block-size)))) (vector-set! output i (proc (vector-ref input i)))) (lp (1+ i)))) (with-mutex mtx (set! n (1+ n)) (signal-condition-variable cnd))) output) output (iota max-thread)) (with-mutex mtx (while (not (< n max-thread)) (wait-condition-variable cnd mtx)))) (let ((base (- (vector-length input) rest))) (let lp ((i 0)) (when (< i rest) (let ((i (+ i base))) (vector-set! output i (proc (vector-ref input i)))) (lp (1+ i))))) output)) --8<---------------cut here---------------end--------------->8--- -- Olivier Dion oldiob.dev ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-12 21:55 ` Olivier Dion via Developers list for Guile, the GNU extensibility library @ 2022-10-13 7:40 ` Damien Mattei 2022-10-13 8:20 ` Damien Mattei 2022-10-13 9:10 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 2022-10-13 10:44 ` Damien Mattei 1 sibling, 2 replies; 27+ messages in thread From: Damien Mattei @ 2022-10-13 7:40 UTC (permalink / raw) Cc: guile-user, guile-devel ok , i think the problem comes both from my code and from guile parmap so. Obviously parmap could be slower on other codes because of the nature of list i think, it is hard to split a list in sublist and send them to thread and after redo a single list, i better use vector. As mentioned and forget by me, i apologize, i use an hash table which is a global variable and mutex can be set on it , no dead lock , here but it slow down the code than it is dead for speed , but not locked. The examples given are good but i do not want to write long and specific code for //, for // must a ssimple as OpenMP directives (on arrays) not be a pain in the ass like things i already did at work with GPUs in C or Fortran,that's nightmare and i do not want to have this in functional programming. ok i will try to modify the code but i do not think there is easy solution to replace the hash table, any structure i would use would be global and the problem (this function is not pure, it does a side-effect),at the end i do not think this code could be // but i'm not a specialist of //. I think this is a parallelization problem, how can we deal with a global variable such as an hash table? On Wed, Oct 12, 2022 at 11:55 PM Olivier Dion <olivier.dion@polymtl.ca> wrote: > On Wed, 12 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: > > Hello, > > all is in the title, i test on a approximately 30000 element list , i got > > 9s with map and 3min 30s with par-map on exactly the same piece of > > code!? > > I can only speculate here. But trying with a very simple example here: > --8<---------------cut here---------------start------------->8--- > (use-modules (statprof)) > (statprof (lambda () (par-map 1+ (iota 300000)))) > --8<---------------cut here---------------end--------------->8--- > > Performance are terrible. I don't know how par-map is implemented, but > if it does 1 element static scheduling -- which it probably does because > you pass a linked list and not a vector -- then yeah you can assure that > thing will be very slow. > > You're probably better off with dynamic scheduling with vectors. Here's > a quick snippet I made for static scheduling but with vectors. Feel > free to roll your own. > > --8<---------------cut here---------------start------------->8--- > (use-modules > (srfi srfi-1) > (ice-9 threads)) > > (define* (par-map-vector proc input > #:optional > (max-thread (current-processor-count))) > > (let* ((block-size (quotient (vector-length input) max-thread)) > (rest (remainder (vector-length input) max-thread)) > (output (make-vector (vector-length input) #f))) > (when (not (zero? block-size)) > (let ((mtx (make-mutex)) > (cnd (make-condition-variable)) > (n 0)) > (fold > (lambda (scale output) > (begin-thread > (let lp ((i 0)) > (when (< i block-size) > (let ((i (+ i (* scale block-size)))) > (vector-set! output i (proc (vector-ref input i)))) > (lp (1+ i)))) > (with-mutex mtx > (set! n (1+ n)) > (signal-condition-variable cnd))) > output) > output > (iota max-thread)) > (with-mutex mtx > (while (not (< n max-thread)) > (wait-condition-variable cnd mtx)))) > (let ((base (- (vector-length input) rest))) > (let lp ((i 0)) > (when (< i rest) > (let ((i (+ i base))) > (vector-set! output i (proc (vector-ref input i)))) > (lp (1+ i))))) > output)) > --8<---------------cut here---------------end--------------->8--- > > -- > Olivier Dion > oldiob.dev > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-13 7:40 ` Damien Mattei @ 2022-10-13 8:20 ` Damien Mattei 2022-10-13 9:10 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 1 sibling, 0 replies; 27+ messages in thread From: Damien Mattei @ 2022-10-13 8:20 UTC (permalink / raw) To: guile-user, guile-devel ok 'parallelization code and hash table' in google show no real solution, i have another idea,instead of function-unify-two-minterms-and-tag ,just unify the minterms and tag them (which use hash table) later out of the // region, after if it still sucks i will drop list for vectors, making it step by step will show where is the bottleneck, let me just a few time and i will go back to the mailing lists with interesting results i hope.... On Thu, Oct 13, 2022 at 9:40 AM Damien Mattei <damien.mattei@gmail.com> wrote: > ok , i think the problem comes both from my code and from guile parmap so. > Obviously parmap could be slower on other codes because of the nature of > list i think, it is hard to split a list in sublist and send them to thread > and after redo a single list, i better use vector. > As mentioned and forget by me, i apologize, i use an hash table which is a > global variable and mutex can be set on it , no dead lock , here but it > slow down the code than it is dead for speed , but not locked. > > The examples given are good but i do not want to write long and specific > code for //, for // must a ssimple as OpenMP directives (on arrays) not be > a pain in the ass like things i already did at work with GPUs in C or > Fortran,that's nightmare and i do not want to have this in functional > programming. > > ok i will try to modify the code but i do not think there is easy solution > to replace the hash table, any structure i would use would be global and > the problem (this function is not pure, it does a side-effect),at the end i > do not think this code could be // but i'm not a specialist of //. I think > this is a parallelization problem, how can we deal with a global variable > such as an hash table? > > On Wed, Oct 12, 2022 at 11:55 PM Olivier Dion <olivier.dion@polymtl.ca> > wrote: > >> On Wed, 12 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: >> > Hello, >> > all is in the title, i test on a approximately 30000 element list , i >> got >> > 9s with map and 3min 30s with par-map on exactly the same piece of >> > code!? >> >> I can only speculate here. But trying with a very simple example here: >> --8<---------------cut here---------------start------------->8--- >> (use-modules (statprof)) >> (statprof (lambda () (par-map 1+ (iota 300000)))) >> --8<---------------cut here---------------end--------------->8--- >> >> Performance are terrible. I don't know how par-map is implemented, but >> if it does 1 element static scheduling -- which it probably does because >> you pass a linked list and not a vector -- then yeah you can assure that >> thing will be very slow. >> >> You're probably better off with dynamic scheduling with vectors. Here's >> a quick snippet I made for static scheduling but with vectors. Feel >> free to roll your own. >> >> --8<---------------cut here---------------start------------->8--- >> (use-modules >> (srfi srfi-1) >> (ice-9 threads)) >> >> (define* (par-map-vector proc input >> #:optional >> (max-thread (current-processor-count))) >> >> (let* ((block-size (quotient (vector-length input) max-thread)) >> (rest (remainder (vector-length input) max-thread)) >> (output (make-vector (vector-length input) #f))) >> (when (not (zero? block-size)) >> (let ((mtx (make-mutex)) >> (cnd (make-condition-variable)) >> (n 0)) >> (fold >> (lambda (scale output) >> (begin-thread >> (let lp ((i 0)) >> (when (< i block-size) >> (let ((i (+ i (* scale block-size)))) >> (vector-set! output i (proc (vector-ref input i)))) >> (lp (1+ i)))) >> (with-mutex mtx >> (set! n (1+ n)) >> (signal-condition-variable cnd))) >> output) >> output >> (iota max-thread)) >> (with-mutex mtx >> (while (not (< n max-thread)) >> (wait-condition-variable cnd mtx)))) >> (let ((base (- (vector-length input) rest))) >> (let lp ((i 0)) >> (when (< i rest) >> (let ((i (+ i base))) >> (vector-set! output i (proc (vector-ref input i)))) >> (lp (1+ i))))) >> output)) >> --8<---------------cut here---------------end--------------->8--- >> >> -- >> Olivier Dion >> oldiob.dev >> > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-13 7:40 ` Damien Mattei 2022-10-13 8:20 ` Damien Mattei @ 2022-10-13 9:10 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 1 sibling, 0 replies; 27+ messages in thread From: Olivier Dion via Developers list for Guile, the GNU extensibility library @ 2022-10-13 9:10 UTC (permalink / raw) To: Damien Mattei; +Cc: guile-user, guile-devel On Thu, 13 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: > ok , i think the problem comes both from my code and from guile parmap so. > Obviously parmap could be slower on other codes because of the nature of > list i think, it is hard to split a list in sublist and send them to thread > and after redo a single list, i better use vector. > As mentioned and forget by me, i apologize, i use an hash table which is a > global variable and mutex can be set on it , no dead lock , here but it > slow down the code than it is dead for speed , but not locked. Your code is not the issue. The fact that `(par-map 1+ (iota 10000000))` is slow is the proof of that. I think that you should use par-map when you want to do I/O/subprocesses in parallel. Fast computation on a huge number of items should be done with vector because of its random access nature. List are simply no the good data structure for parallelization. > The examples given are good but i do not want to write long and specific > code for //, for // must a ssimple as OpenMP directives (on arrays) not be > a pain in the ass like things i already did at work with GPUs in C or > Fortran,that's nightmare and i do not want to have this in functional > programming. You're free to use my example of `par-map-vector` and tweak it to your needs. But maybe it's time for a `guile-parallel` for fast high level parallel. If others are interested in that, I can make one. -- Olivier Dion oldiob.dev ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-12 21:55 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 2022-10-13 7:40 ` Damien Mattei @ 2022-10-13 10:44 ` Damien Mattei 2022-10-13 11:00 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 1 sibling, 1 reply; 27+ messages in thread From: Damien Mattei @ 2022-10-13 10:44 UTC (permalink / raw) To: Olivier Dion, guile-user, guile-devel [-- Attachment #1: Type: text/plain, Size: 2663 bytes --] i trying to use your code but it seems there is a ) mismatch somewhere? On Wed, Oct 12, 2022 at 11:55 PM Olivier Dion <olivier.dion@polymtl.ca> wrote: > On Wed, 12 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: > > Hello, > > all is in the title, i test on a approximately 30000 element list , i got > > 9s with map and 3min 30s with par-map on exactly the same piece of > > code!? > > I can only speculate here. But trying with a very simple example here: > --8<---------------cut here---------------start------------->8--- > (use-modules (statprof)) > (statprof (lambda () (par-map 1+ (iota 300000)))) > --8<---------------cut here---------------end--------------->8--- > > Performance are terrible. I don't know how par-map is implemented, but > if it does 1 element static scheduling -- which it probably does because > you pass a linked list and not a vector -- then yeah you can assure that > thing will be very slow. > > You're probably better off with dynamic scheduling with vectors. Here's > a quick snippet I made for static scheduling but with vectors. Feel > free to roll your own. > > --8<---------------cut here---------------start------------->8--- > (use-modules > (srfi srfi-1) > (ice-9 threads)) > > (define* (par-map-vector proc input > #:optional > (max-thread (current-processor-count))) > > (let* ((block-size (quotient (vector-length input) max-thread)) > (rest (remainder (vector-length input) max-thread)) > (output (make-vector (vector-length input) #f))) > (when (not (zero? block-size)) > (let ((mtx (make-mutex)) > (cnd (make-condition-variable)) > (n 0)) > (fold > (lambda (scale output) > (begin-thread > (let lp ((i 0)) > (when (< i block-size) > (let ((i (+ i (* scale block-size)))) > (vector-set! output i (proc (vector-ref input i)))) > (lp (1+ i)))) > (with-mutex mtx > (set! n (1+ n)) > (signal-condition-variable cnd))) > output) > output > (iota max-thread)) > (with-mutex mtx > (while (not (< n max-thread)) > (wait-condition-variable cnd mtx)))) > (let ((base (- (vector-length input) rest))) > (let lp ((i 0)) > (when (< i rest) > (let ((i (+ i base))) > (vector-set! output i (proc (vector-ref input i)))) > (lp (1+ i))))) > output)) > --8<---------------cut here---------------end--------------->8--- > > -- > Olivier Dion > oldiob.dev > [-- Attachment #2: Type: text/html, Size: 3591 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-13 10:44 ` Damien Mattei @ 2022-10-13 11:00 ` Olivier Dion via Developers list for Guile, the GNU extensibility library [not found] ` <CADEOadfovi8s3OxRcssWOuOW8jjHoL9Z7pD_5FstSm=ZkBHP8g@mail.gmail.com> 0 siblings, 1 reply; 27+ messages in thread From: Olivier Dion via Developers list for Guile, the GNU extensibility library @ 2022-10-13 11:00 UTC (permalink / raw) To: Damien Mattei, guile-user, guile-devel On Thu, 13 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: > i trying to use your code but it seems there is a ) mismatch > somewhere? Right there's a missing ')' a the end to close the procedure, sorry about that. -- Olivier Dion oldiob.dev ^ permalink raw reply [flat|nested] 27+ messages in thread
[parent not found: <CADEOadfovi8s3OxRcssWOuOW8jjHoL9Z7pD_5FstSm=ZkBHP8g@mail.gmail.com>]
* Fwd: map-par slower than map [not found] ` <CADEOadfovi8s3OxRcssWOuOW8jjHoL9Z7pD_5FstSm=ZkBHP8g@mail.gmail.com> @ 2022-10-13 11:57 ` Damien Mattei 2022-10-13 12:36 ` Damien Mattei 0 siblings, 1 reply; 27+ messages in thread From: Damien Mattei @ 2022-10-13 11:57 UTC (permalink / raw) To: guile-user, guile-devel sorry google always do reply to single author... ---------- Forwarded message --------- From: Damien Mattei <damien.mattei@gmail.com> Date: Thu, Oct 13, 2022 at 1:56 PM Subject: Re: map-par slower than map To: Olivier Dion <olivier.dion@polymtl.ca> ah just at the end? i had noticed, but i get #unspecifeid ? so my new code is not good if your procedure is, i will check it,thanks. Damien On Thu, Oct 13, 2022 at 1:00 PM Olivier Dion <olivier.dion@polymtl.ca> wrote: > On Thu, 13 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: > > i trying to use your code but it seems there is a ) mismatch > > somewhere? > > Right there's a missing ')' a the end to close the procedure, sorry > about that. > > -- > Olivier Dion > oldiob.dev > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-13 11:57 ` Fwd: " Damien Mattei @ 2022-10-13 12:36 ` Damien Mattei 2022-10-13 12:41 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 0 siblings, 1 reply; 27+ messages in thread From: Damien Mattei @ 2022-10-13 12:36 UTC (permalink / raw) To: guile-user, guile-devel, Olivier Dion the code did not worked when data length were more little than number of cpus (6 on my host) (iota 5) returns #unsepcified: scheme@(guile-user)> (use-modules (ice-9 threads)) scheme@(guile-user)> {v <+ (list->vector (iota 5))} #(0 1 2 3 4) scheme@(guile-user)> (par-map-vector sqrt v) scheme@(guile-user)> {v <+ (list->vector (iota 20))} #(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19) scheme@(guile-user)> (par-map-vector sqrt v) #(0 1 1.4142135623730951 1.7320508075688772 2 2.23606797749979 2.449489742783178 2.6457513110645907 2.8284271247461903 3 3.1622776601683795 3.3166247903554 3.4641016151377544 3.605551275463989 3.7416573867739413 3.872983346207417 4 4.123105625617661 4.242640687119285 4.358898943540674) scheme@(guile-user)> (current-processor-count) 6 scheme@(guile-user)> {v <+ (list->vector (iota 6))} #(0 1 2 3 4 5) scheme@(guile-user)> (par-map-vector sqrt v) #(0 1 1.4142135623730951 1.7320508075688772 2 2.23606797749979) so i modify it this way: (define* (par-map-vector proc input #:optional (max-thread (current-processor-count))) (if (< (vector-length input) max-thread) (list->vector (map proc (vector->list input))) ;; less data than threads or CPUs (let* ((block-size (quotient (vector-length input) max-thread)) (rest (remainder (vector-length input) max-thread)) (output (make-vector (vector-length input) #f))) (when (not (zero? block-size)) (let ((mtx (make-mutex)) (cnd (make-condition-variable)) (n 0)) (fold (lambda (scale output) (begin-thread (let lp ((i 0)) (when (< i block-size) (let ((i (+ i (* scale block-size)))) (vector-set! output i (proc (vector-ref input i)))) (lp (1+ i)))) (with-mutex mtx (set! n (1+ n)) (signal-condition-variable cnd))) output) output (iota max-thread)) (with-mutex mtx (while (not (< n max-thread)) (wait-condition-variable cnd mtx)))) (let ((base (- (vector-length input) rest))) (let lp ((i 0)) (when (< i rest) (let ((i (+ i base))) (vector-set! output i (proc (vector-ref input i)))) (lp (1+ i))))) output)))) now it works but crash randomly, not even at the same stage, i continue to test and debug.... On Thu, Oct 13, 2022 at 1:57 PM Damien Mattei <damien.mattei@gmail.com> wrote: > sorry google always do reply to single author... > > ---------- Forwarded message --------- > From: Damien Mattei <damien.mattei@gmail.com> > Date: Thu, Oct 13, 2022 at 1:56 PM > Subject: Re: map-par slower than map > To: Olivier Dion <olivier.dion@polymtl.ca> > > > ah just at the end? i had noticed, but i get #unspecifeid ? so my new code > is not good if your procedure is, i will check it,thanks. > Damien > > On Thu, Oct 13, 2022 at 1:00 PM Olivier Dion <olivier.dion@polymtl.ca> > wrote: > >> On Thu, 13 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: >> > i trying to use your code but it seems there is a ) mismatch >> > somewhere? >> >> Right there's a missing ')' a the end to close the procedure, sorry >> about that. >> >> -- >> Olivier Dion >> oldiob.dev >> > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-13 12:36 ` Damien Mattei @ 2022-10-13 12:41 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 2022-10-13 13:43 ` Damien Mattei 0 siblings, 1 reply; 27+ messages in thread From: Olivier Dion via Developers list for Guile, the GNU extensibility library @ 2022-10-13 12:41 UTC (permalink / raw) To: Damien Mattei, guile-user, guile-devel On Thu, 13 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: > the code did not worked when data length were more little than number of > cpus (6 on my host) (iota 5) returns #unsepcified: Yeah sorry I miss indended the output and the rest. Here's a version that should work: --8<---------------cut here---------------start------------->8--- (use-modules (srfi srfi-1) (ice-9 threads)) (define* (par-map-vector proc input #:optional (max-thread (current-processor-count))) (let* ((block-size (quotient (vector-length input) max-thread)) (rest (remainder (vector-length input) max-thread)) (output (make-vector (vector-length input) #f))) (when (not (zero? block-size)) (let ((mtx (make-mutex)) (cnd (make-condition-variable)) (n 0)) (fold (lambda (scale output) (begin-thread (let lp ((i 0)) (when (< i block-size) (let ((i (+ i (* scale block-size)))) (vector-set! output i (proc (vector-ref input i)))) (lp (1+ i)))) (with-mutex mtx (set! n (1+ n)) (signal-condition-variable cnd))) output) output (iota max-thread)) (with-mutex mtx (while (not (< n max-thread)) (wait-condition-variable cnd mtx))))) (let ((base (- (vector-length input) rest))) (let lp ((i 0)) (when (< i rest) (let ((i (+ i base))) (vector-set! output i (proc (vector-ref input i)))) (lp (1+ i))))) output)) --8<---------------cut here---------------end--------------->8--- -- Olivier Dion oldiob.dev ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-13 12:41 ` Olivier Dion via Developers list for Guile, the GNU extensibility library @ 2022-10-13 13:43 ` Damien Mattei 2022-10-13 14:06 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 0 siblings, 1 reply; 27+ messages in thread From: Damien Mattei @ 2022-10-13 13:43 UTC (permalink / raw) To: Olivier Dion; +Cc: guile-user, guile-devel i do not see what has changed in your code ? really strange,even with bad code the moment it crash should be the same, sometimes works,crash or freeze.... On Thu, Oct 13, 2022 at 2:41 PM Olivier Dion <olivier.dion@polymtl.ca> wrote: > On Thu, 13 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: > > the code did not worked when data length were more little than number of > > cpus (6 on my host) (iota 5) returns #unsepcified: > > Yeah sorry I miss indended the output and the rest. Here's a version > that should work: > --8<---------------cut here---------------start------------->8--- > (use-modules > (srfi srfi-1) > (ice-9 threads)) > > (define* (par-map-vector proc input > #:optional > (max-thread (current-processor-count))) > > (let* ((block-size (quotient (vector-length input) max-thread)) > (rest (remainder (vector-length input) max-thread)) > (output (make-vector (vector-length input) #f))) > (when (not (zero? block-size)) > (let ((mtx (make-mutex)) > (cnd (make-condition-variable)) > (n 0)) > (fold > (lambda (scale output) > (begin-thread > (let lp ((i 0)) > (when (< i block-size) > (let ((i (+ i (* scale block-size)))) > (vector-set! output i (proc (vector-ref input i)))) > (lp (1+ i)))) > (with-mutex mtx > (set! n (1+ n)) > (signal-condition-variable cnd))) > output) > output > (iota max-thread)) > (with-mutex mtx > (while (not (< n max-thread)) > (wait-condition-variable cnd mtx))))) > (let ((base (- (vector-length input) rest))) > (let lp ((i 0)) > (when (< i rest) > (let ((i (+ i base))) > (vector-set! output i (proc (vector-ref input i)))) > (lp (1+ i))))) > output)) > --8<---------------cut here---------------end--------------->8--- > > -- > Olivier Dion > oldiob.dev > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-13 13:43 ` Damien Mattei @ 2022-10-13 14:06 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 2022-10-13 14:10 ` Damien Mattei 0 siblings, 1 reply; 27+ messages in thread From: Olivier Dion via Developers list for Guile, the GNU extensibility library @ 2022-10-13 14:06 UTC (permalink / raw) To: Damien Mattei; +Cc: guile-user, guile-devel On Thu, 13 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: > i do not see what has changed in your code ? Just copy it. Trust me it has changed. > really strange,even with bad code the moment it crash should be the same, > sometimes works,crash or freeze.... I don't get any of these problem .. running with (iota 100000000) I don't see any synchornization issue also. -- Olivier Dion oldiob.dev ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-13 14:06 ` Olivier Dion via Developers list for Guile, the GNU extensibility library @ 2022-10-13 14:10 ` Damien Mattei 2022-10-13 14:21 ` Damien Mattei 0 siblings, 1 reply; 27+ messages in thread From: Damien Mattei @ 2022-10-13 14:10 UTC (permalink / raw) To: Olivier Dion; +Cc: guile-user, guile-devel On Thu, Oct 13, 2022 at 4:06 PM Olivier Dion <olivier.dion@polymtl.ca> wrote: > On Thu, 13 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: > > i do not see what has changed in your code ? > > Just copy it. Trust me it has changed. > really ? :-) i read it 3 times line by line, yes the end is cut ,still no ending ) and i use it and freeze,crash or ok randomly, the first times it works but try 4 or 5 examples.... :-( > > > really strange,even with bad code the moment it crash should be the same, > > sometimes works,crash or freeze.... > > I don't get any of these problem .. running with (iota 100000000) I > don't see any synchornization issue also. > > -- > Olivier Dion > oldiob.dev > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: map-par slower than map 2022-10-13 14:10 ` Damien Mattei @ 2022-10-13 14:21 ` Damien Mattei 0 siblings, 0 replies; 27+ messages in thread From: Damien Mattei @ 2022-10-13 14:21 UTC (permalink / raw) To: Olivier Dion; +Cc: guile-user, guile-devel ok i have the proof, this time (second time) the process stopped itself on your example ("processus stoppé " in french) : mattei@pc-mattei:~/Dropbox/git/library-FunctProg$ guile GNU Guile 3.0.1 Copyright (C) 1995-2020 Free Software Foundation, Inc. Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. This program is free software, and you are welcome to redistribute it under certain conditions; type `,show c' for details. Enter `,help' for help. scheme@(guile-user)> (use-modules (srfi srfi-1) (ice-9 threads)) scheme@(guile-user)> (define* (par-map-vector proc input #:optional (max-thread (current-processor-count))) (if (< (vector-length input) max-thread) (list->vector (map proc (vector->list input))) ;; less data than threads or CPUs (let* ((block-size (quotient (vector-length input) max-thread)) (rest (remainder (vector-length input) max-thread)) (output (make-vector (vector-length input) #f))) (when (not (zero? block-size)) (let ((mtx (make-mutex)) (cnd (make-condition-variable)) (n 0)) (fold (lambda (scale output) (begin-thread (let lp ((i 0)) (when (< i block-size) (let ((i (+ i (* scale block-size)))) (vector-set! output i (proc (vector-ref input i)))) (lp (1+ i)))) (with-mutex mtx (set! n (1+ n)) (signal-condition-variable cnd))) output) output (iota max-thread)) (with-mutex mtx (while (not (< n max-thread)) (wait-condition-variable cnd mtx)))) ;; (let ((base (- (vector-length input) rest))) ;; (let lp ((i 0)) ;; (when (< i rest) ;; (let ((i (+ i base))) ;; (vector-set! output i (proc (vector-ref input i)))) ;; (lp (1+ i))))) output)))) scheme@(guile-user)> (define v (list->vector (iota 100000000) )) scheme@(guile-user)> (define r (par-map-vector sqrt v)) scheme@(guile-user)> (define v (list->vector (iota 100000000) )) scheme@(guile-user)> (define r (par-map-vector sqrt v)) Processus arrêté the first time is ok but the second time, Guile quit to the terminal. seems something makes the guile system instable after one run, i test it out of my program and out of my Scheme+ but my .guile is in this directory like that: ; Guile config file ;; history (use-modules (ice-9 readline) (ice-9 history) (srfi srfi-43) ;; vector ;; guile object oriented programming system (oop goops) (oop goops describe)) (activate-readline) ;;(disable-value-history!) ;; curly infix as in srfi-105 (read-enable 'curly-infix) ;; set current path in load path (set! %load-path (reverse (cons "." (reverse %load-path)))) ;; other solution is to put this in shell: ;; export GUILE_LOAD_PATH="...:." On Thu, Oct 13, 2022 at 4:10 PM Damien Mattei <damien.mattei@gmail.com> wrote: > > > On Thu, Oct 13, 2022 at 4:06 PM Olivier Dion <olivier.dion@polymtl.ca> > wrote: > >> On Thu, 13 Oct 2022, Damien Mattei <damien.mattei@gmail.com> wrote: >> > i do not see what has changed in your code ? >> >> Just copy it. Trust me it has changed. >> > really ? :-) i read it 3 times line by line, yes the end is cut ,still no > ending ) and i use it and freeze,crash or ok randomly, the first times it > works but try 4 or 5 examples.... :-( > >> >> > really strange,even with bad code the moment it crash should be the >> same, >> > sometimes works,crash or freeze.... >> >> I don't get any of these problem .. running with (iota 100000000) I >> don't see any synchornization issue also. >> >> -- >> Olivier Dion >> oldiob.dev >> > ^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2022-10-25 14:09 UTC | newest] Thread overview: 27+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-10-12 17:19 map-par slower than map Damien Mattei 2022-10-12 18:45 ` Maxime Devos 2022-10-12 20:20 ` Damien Mattei 2022-10-12 20:27 ` Damien Mattei 2022-10-12 21:29 ` Zelphir Kaltstahl 2022-10-14 8:21 ` Damien Mattei 2022-10-14 8:38 ` Zelphir Kaltstahl 2022-10-17 13:17 ` Damien Mattei 2022-10-22 16:01 ` Damien Mattei 2022-10-23 1:06 ` Damien Mattei 2022-10-25 9:07 ` Mikael Djurfeldt 2022-10-25 9:11 ` Mikael Djurfeldt 2022-10-25 14:09 ` Damien Mattei 2022-10-12 21:44 ` Maxime Devos 2022-10-12 21:55 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 2022-10-13 7:40 ` Damien Mattei 2022-10-13 8:20 ` Damien Mattei 2022-10-13 9:10 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 2022-10-13 10:44 ` Damien Mattei 2022-10-13 11:00 ` Olivier Dion via Developers list for Guile, the GNU extensibility library [not found] ` <CADEOadfovi8s3OxRcssWOuOW8jjHoL9Z7pD_5FstSm=ZkBHP8g@mail.gmail.com> 2022-10-13 11:57 ` Fwd: " Damien Mattei 2022-10-13 12:36 ` Damien Mattei 2022-10-13 12:41 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 2022-10-13 13:43 ` Damien Mattei 2022-10-13 14:06 ` Olivier Dion via Developers list for Guile, the GNU extensibility library 2022-10-13 14:10 ` Damien Mattei 2022-10-13 14:21 ` Damien Mattei
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).