问题
If I have a program like the one below, does prolog try to prove maximum/3
all three times in parallel? i.e does each thread get its own core (assuming available on the computer)?
My actual program takes about 2 hours to run a predicate in the position of maximum/3
here and I have 70 equivalent of pair/2
that will need to be calculated. Would this approach work? If not why not? I have set the program running but it seems from the output that it is just doing one thread at a time.
maximum(X,Y,Y) :- X =< Y,!.
maximum(X,_,X).
pair(5,6).
pair(8,7).
pair(9,9).
thread(A,B,Stream) :-
maximum(A,B,C),
format(Stream, "max('~w','~w',~w).~n",[A,B,C]),
thread_exit(C).
start(File) :-
open(File,append,Stream,[]),
forall(
pair(A,B),
(
thread_create(thread(A,B,Stream),Id,[]),
thread_join(Id,exited(X)),
writeln(X)
)
),
close(Stream).
回答1:
You can simplify your code by taking advantage of the SWI-Prolog concurrent/3
library predicate:
http://www.swi-prolog.org/pldoc/doc_for?object=thread:concurrent/3
Another option is Logtalk's support for high-level multi-threading programming (SWI-Prolog is one of the backend Prolog compilers it supports).
In any case, it's a two step process: first create the goals (that should be executed in parallel) and, second, run them. But you're not doing that. SWI-Prolog threads are created (by default) as non-detached. The call to thread_join/2
predicate in your code means that you're waiting for the thread you just created to finish before passing to the next pair. Thus, you're correct and your code is running one thread at a time. Try:
maximum(X,Y,Y) :- X =< Y,!.
maximum(X,_,X).
pair(5,6).
pair(8,7).
pair(9,9).
thread(A,B,Stream) :-
maximum(A,B,C),
format(Stream, "max('~w','~w',~w).~n",[A,B,C]).
start(File) :-
open(File,append,Stream,[]),
findall(thread(A,B,Stream), pair(A,B), Goals),
length(Goals, N),
concurrent(N, Goals, []),
close(Stream).
Sample execution:
?- [concurrent].
true.
?- start(results).
true.
?-
% halt
$ cat results
max('5','6',6).
max('8','7',8).
max('9','9',9).
Using the number of goals as the number of threads (aka workers) to use is, however, not the best choice. Likely better to use a value for N
derived from the number of cores (or the number of threads each core can run) of your hardware.
The Logtalk solution is similar (but more portable) using its threaded/1
built-in predicate (but it takes a goal conjunction instead of a goal list).
来源:https://stackoverflow.com/questions/26849346/swi-prolog-threads-with-stream-output