带流输出的SWI-Prolog线程 [英] SWI-Prolog threads with stream output

查看:65
本文介绍了带流输出的SWI-Prolog线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有一个类似于以下程序的程序,那么prolog是否会尝试同时并行地证明maximum/3三次?即每个线程都有自己的核心(假设计算机上可用)吗?

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)?

我的实际程序需要大约2个小时才能在此处的maximum/3位置运行谓词,而我有70个等价的pair/2需要进行计算.这种方法行得通吗?如果不是,为什么不呢?我已将程序设置为运行,但是从输出中看来,它一次只执行一个线程.

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).

推荐答案

您可以利用SWI-Prolog concurrent/3库谓词来简化代码:

You can simplify your code by taking advantage of the SWI-Prolog concurrent/3 library predicate:

另一个选择是Logtalk对高级多线程编程的支持(SWI-Prolog是它支持的后端Prolog编译器之一).

Another option is Logtalk's support for high-level multi-threading programming (SWI-Prolog is one of the backend Prolog compilers it supports).

无论如何,这是一个两步过程:首先创建目标(应并行执行),然后运行目标.但是你没有那样做. SWI-Prolog线程(默认情况下)创建为未分离.在代码中对thread_join/2谓词的调用意味着您正在等待刚创建的线程完成,然后再传递给下一个对.因此,您是正确的,并且您的代码一次运行一个线程.试试:

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).

示例执行:

?- [concurrent].
true.

?- start(results).
true.

?- 
% halt
$ cat results
max('5','6',6).
max('8','7',8).
max('9','9',9).

使用目标数作为要使用的线程数(即工作程序数)不是最佳选择.最好使用从硬件的内核数(或每个内核可以运行的线程数)得出的N值.

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.

Logtalk解决方案使用其threaded/1内置谓词类似(但更具可移植性)(但它采用目标并列而不是目标列表).

The Logtalk solution is similar (but more portable) using its threaded/1built-in predicate (but it takes a goal conjunction instead of a goal list).

这篇关于带流输出的SWI-Prolog线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆