My problem: apply a predicate to filter a list in parallel
I have a list, and I have a predicate. In practice, it's a long list and the predicate takes a while. I want to output just the elements of the list which satisfy the predicate.
I have access to lots of CPU cores, so I thought it would make sense to try to test the elements of the list in blocks in parallel.
Stuff I've tried:
[concurrent_
]maplist
doesn't work
Seems like it should be easy. concurrent_maplist
seems like an easy concurrent version of maplist
.
According to another answer on this site, maplist/3
should do exactly what I want. The docs for SWI's maplist/3
suggest maybe it doesn't behave as described in the answer, but in the comments the author of the answer suggests that is an issue with the docs and it should indeed work as expected.
It doesn't seem to work for me.
I've tested this as follows:
:- use_module(library(apply)).
f(A):-
(A*A < 10),
writeln(A).
set(0,[]).
set(N,T):- N2 is N-1, set(N2,T1), append(T1,[N],T).
This doesn't work:
?- set(4,L), concurrent_maplist(f, L, O).
ERROR: Undefined procedure: f/2
ERROR: However, there are definitions for:
ERROR: f/1
Same issue with plain maplist
:
set(4,L), maplist(f, L, O).
ERROR: Undefined procedure: f/2
ERROR: However, there are definitions for:
ERROR: f/1
include
works but isn't parallel
What does do what I want (not in parallel tho) is include
:
?- set(11,L), include(f, L, O).
1
2
3
L = [1, 2, 3, 4, 5, 6, 7, 8, 9|...],
O = [1, 2, 3] .
concurrent
[edit] runs! But is it parallel?
I've been trying to get it work using concurrent/3
partly following the example of another answer.
Loading this file:
set(0,[]):-!.
set(N,T):- N2 is N-1, set(N2,T1), append(T1,[N],T).
f(A, B):-
(A*A < B),
writeln(A).
par_test(A, B):-
set(A, S),
findall(f(Good, B), (member(Good, S)), Goals),
concurrent(8, Goals, []).
...
?- set(4, S), findall(f(Good, 4), member(Good, S), Goals), concurrent(8, Goals, []).
1
false.
But watching htop
(with a much longer-running predicate in place of this f
), it seems to run on just one core :-(.
How do I do this in parallel?
Is there a way to achieve this with concurrent_maplist
, or a similarly easy parallel version of include
, or another way to achieve what I'm going for?