Scala任务并行化与actors =>调度程序如何工作?

时间:2012-11-26 10:49:45

标签: scala parallel-processing scheduling actor producer-consumer

我有一项任务可以很容易地分成可以并且应该并行处理以优化性能的部分。

我写了一个制作人演员,它准备了可以独立处理的任务的每个部分。这种准备相对便宜。

我写了一个处理每个独立任务的消费者Actor。根据参数,每个独立任务可能需要几秒钟才能处理。所有任务都完全相同。它们都处理相同的算法,具有相同数量的数据(但当然是不同的值),导致大致相同的处理时间。

因此,制作人比消费者快得多。因此,很快就可以准备200或2000个任务(取决于参数)。所有这些都消耗内存,而其中只有几个可以同时执行。

现在我看到两种简单的策略来消费和处理任务:

  1. 为每项任务创建一个新的消费者角色实例。

    • 每个消费者仅处理任务。
    • 我假设同时会有许多消费者角色实例,而其中只有几个可以在任何时间处理。
    • 默认调度程序如何工作?每个消费者演员可以在下一个消费者安排之前完成处理吗?或者消费者是否会被中断并被另一个消费者所取代,从而导致第一个任务完成之前的时间更长?我认为这个actor调度与进程或线程调度不同,但我可以想象,中断仍然有一些缺点(例如更多的缓存未命中)。
  2. 另一种策略是使用消费者角色的N个实例,并将任务作为消息发送给他们。

    • 每个消费者按顺序处理多个任务。
    • 我需要找到N(消费者数量)的合适值。
    • N个消费者的任务分配也由我自己决定。
  3. 我可以想象一个更复杂的解决方案,在生产者和消费者之间进行更多的协调,但如果不了解调度程序,我就无法做出正确的决定。

  4. 如果手动解决方案不会带来明显更好的性能,我宁愿使用默认解决方案(由Scala世界的某些部分提供),其中调度任务不会由我决定(如策略1)。

    问题综述:

    • 默认调度程序如何工作?
      • 每个消费者演员可以在下一个消费者安排之前完成处理吗?
      • 或者消费者是否会被中断并被其他消费者所取代,从而导致第一项任务完成之前的时间更长?
      • 调度程序经常中断演员并安排另一个演员时有什么缺点?高速缓存未命中?
      • 这种中断和调度是否会像进程调度或线程调度中的上下文更改一样?
    • 比较这些策略是否还有其他优点或缺点?
    • 特别是战略1在策略2方面有缺点吗?
    • 哪种策略最好?
    • 是否有比我提议的更好的策略?

    我担心,像前两个这样的问题无法得到绝对的回答,但这次也许这是可能的,因为我试图尽可能具体地说明案例。

    我认为其他问题可以在没有多少讨论的情况下得到解答。有了这些答案,就应该可以选择最符合要求的策略。

    我自己做了一些研究和思考,并提出了一些假设。如果这些假设有任何错误,请告诉我。

3 个答案:

答案 0 :(得分:0)

如果我是你,我会继续使用2 nd选项。每个任务的新actor实例太繁琐了。此外,通过N的智能决策,可以使用完整的系统资源。

虽然这不是一个完整的解决方案。但是一个可能的选择是,生产者不能停止/减慢生产任务的速度吗?这将是理想的。只有当有消费者或其他东西时,生产者才会产生更多的任务。

答案 1 :(得分:0)

假设你正在使用Akka(如果你没有,你应该;-)),你可以使用SmallestMailboxRouter来启动一些演员(你也可以添加一个Resizer)和消息分发将根据一些规则处理。您可以阅读有关路由器here的所有信息。

答案 2 :(得分:0)

对于这样一个简单的任务,演员完全没有利润。将生产者实现为Thread,将每个任务实现为Runnable。使用java.util.concurrent中的线程池来运行任务。使用java.util.concurrent。信号量限制准备和运行任务的数量:在创建下一个任务之前,生产者获取sempahore,每个任务在执行结束时释放信号量。