【发布时间】:2012-11-26 10:49:45
【问题描述】:
我有一个任务可以很容易地分解成可以并且应该并行处理以优化性能的部分。
我编写了一个生产者actor,它准备了可以独立处理的任务的每个部分。这种制剂相对便宜。
我编写了一个消费者 Actor 来处理每个独立的任务。根据参数,每个独立任务可能需要几秒钟的时间来处理。所有的任务都是一样的。它们都处理相同的算法,使用相同数量的数据(当然是不同的值)导致处理时间大致相同。
所以生产者比消费者快得多。因此,很快可能准备好 200 或 2000 个任务(取决于参数)。所有这些都消耗内存,而一次只能执行其中的几个。
现在我看到了使用和处理任务的两种简单策略:
-
为每个任务创建一个新的消费者参与者实例。
- 每个消费者只处理任务。
- 我假设会同时存在许多消费者参与者实例,而其中只有几个可以在任何时间点进行处理。
- 默认调度程序如何工作?每个消费者参与者能否在安排下一个消费者之前完成处理?或者一个消费者会被打断并被另一个消费者取代,导致第一个任务完成的时间更长?我认为这种actor调度与进程或线程调度不同,但我可以想象,这种中断仍然有一些缺点(例如更多的缓存未命中)。
-
另一种策略是使用消费者参与者的 N 个实例并将要处理的任务作为消息发送给它们。
- 每个消费者按顺序处理多个任务。
- 由我自己来为 N(消费者数量)找到一个合适的值。
- N 个消费者的任务分配也由我决定。
我可以想象一个更复杂的解决方案,在生产者和消费者之间进行更多协调,但如果不了解调度程序,我无法做出正确的决定。
如果手动解决方案不会显着提高性能,我更喜欢默认解决方案(由 Scala 世界的某些部分提供),其中调度任务不由我决定(如策略 1)。
问题综述:
- 默认调度程序如何工作?
- 每个消费者参与者能否在安排下一个消费者之前完成处理?
- 或者消费者是否会被中断并被另一个消费者替换,从而导致第一个任务完成之前的时间更长?
- 当调度器频繁中断一个actor并调度另一个actor时有什么缺点?缓存未命中?
- 这种中断和调度是否类似于进程调度或线程调度中的上下文更改?
- 比较这些策略是否还有其他优势或劣势?
- 尤其是策略 1 相对于策略 2 有劣势吗?
- 以下哪种策略最好?
- 有比我建议的更好的策略吗?
我担心,像最后两个这样的问题不能绝对回答,但也许这次是可能的,因为我试图尽可能具体地给出一个案例。
我认为其他问题无需过多讨论即可回答。有了这些答案,应该可以选择最符合要求的策略。
我自己做了一些研究和思考,并提出了一些假设。如果这些假设有任何错误,请告诉我。
【问题讨论】:
标签: scala parallel-processing scheduling actor producer-consumer