【发布时间】:2019-09-19 08:48:27
【问题描述】:
我想定义一个谓词,将一些谓词作为输入
具有相应的输入(它们可以作为惰性调用序列给出),
并行运行它们并计算结果的逻辑或,
这样,当谓词调用终止返回true时,
整个计算也终止(返回true)。
除了提供时间优化,这也有助于避免
在某些情况下不终止(某些谓词调用可能不会终止)。
实际上,将不终止解释为第三个undefined 值,
此谓词模拟 Kleene's K3 logic 中的 or 操作
(初始居中Kleene algebra中的join)。
here 为 Haskell 家族提供了类似的东西。 在 Clojure 中是否有任何(最好是简单的)方法可以做到这一点?
编辑:我决定在阅读 cmets 后添加一些说明。
(a) 首先,线程池耗尽后发生的事情并不重要。我认为创建一个足够大的线程池来满足我们的需求是一个合理的约定。
(b) 最关键的要求是谓词调用开始并行运行,一旦谓词调用终止返回true,所有其他运行的线程都会中断。预期的行为是:
- 如果有谓词调用返回
true:并行或返回true - else 如果存在未终止的谓词调用:并行或未终止
- else:并行或返回
false
换句话说,它的行为类似于falseundefinedtrue 给出的三元素格中的连接,undefined 表示非终止。
(c) 并行的 or 应该能够将许多谓词和许多谓词输入(每个都对应一个谓词)作为输入。但如果将惰性序列作为输入会更好。然后,命名并行或pany(用于“并行任何”),我们可以进行如下调用:
(pany (map (comp eval list) predicates inputs))(pany (map (comp eval list) predicates (repeat input)))-
(pany (map (comp eval list) (repeat predicate) inputs))相当于(pany (map predicate (unchunk inputs)))
作为最后的评论,我认为要求 pany、双重 pall 或用于构建此类早期终止并行缩减以易于实施甚至内置的机制是很自然的Clojure 等面向并行的语言。
【问题讨论】:
-
经过几次尝试,我最终得到了this。它将在可调整大小的 Java 线程池中运行谓词检查,并在找到结果后立即跳过进一步的检查。问题是,我没有发布答案的原因是,如果没有找到真正的结果,这段代码将无限期挂起,因为承诺永远不会被交付,所以取消承诺将永远阻塞。我找不到解决方案,但我想我会发布我所拥有的,以防它可以构建。
-
我想问题是如果前 n 个结果未能终止,其中 n 是您的线程池的大小,那么我们将永远不会返回。认为它可能需要可中断的操作。
-
您希望在找到结果后取消当前正在运行的检查,还是只想阻止新的检查开始?如果是后者,请参阅我的new version of
check-in-par。我从promise获得了一些灵感,修复了之前的问题。不幸的是,它需要知道谓词列表的长度。我不明白你怎么能避免这种情况。您必须以某种方式知道检查何时完成才能报告失败。 -
@Carcigenicate 我认为任何解决方案都将涉及做一些道德上等同于计算输入的事情。更让我担心的是:如果有 N 个(这里是 4 个)或更多任务永远无法完成怎么办?您的线程池充满了卡住的线程。在我看来,Fork/Join 和 CompletableFuture 在这里可能会有所帮助,但我不确定:他们可能不喜欢工作线程只是爬进一个洞。
-
@amalloy 你可以从
execute切换到使用submit,如果你有一个合理的执行时间上限(我认为返回的Futures 允许这样做),那么任务就会超时。你也可以从一个固定的线程池切换到一个像newCachedThreadPool返回的更动态的线程池。如果任务有可能永远无法完成,那么添加超时是我能看到的唯一选择,因为扩展池只会允许更多无限的作业一次坐在池中。
标签: clojure parallel-processing functional-programming logic terminate