Scala - 在多个线程内完成工作的最佳API

时间:2014-12-12 12:28:20

标签: multithreading scala multiprocessing

在Python中,我使用的是一个名为futures的库,它允许我以简洁明了的方式对N个工作进程池进行处理:

schedulerQ = []
for ... in ...:
    workParam = ...  # arguments for call to processingFunction(workParam)
    schedulerQ.append(workParam)
with futures.ProcessPoolExecutor(max_workers=5) as executor:  # 5 CPUs
    for retValue in executor.map(processingFunction, schedulerQ):
        print "Received result", retValue

processingFunction是CPU绑定的,因此这里没有异步机制 - 这是关于简单的算术计算)

我现在正在寻找在Scala中做同样事情的最接近的方法。请注意,在Python中,为了避免GIL问题,我使用了进程(因此使用ProcessPoolExecutor而不是ThreadPoolExecutor) - 并且库自动将workParam参数封送到每个流程实例执行processingFunction(workParam) - 并将结果编组回主进程,以便执行程序的map循环使用。

这适用于Scala和JVM吗?我的processingFunction原则上也可以从线程执行(根本没有全局状态) - 但是我有兴趣看到多处理和多线程的解决方案。

问题的关键部分是JVM世界中是否有任何与您在上面看到的Python futures一样明确的API ...我认为这是最好的SMP API之一曾经见过 - 使用所有调用的函数参数准备一个列表,然后只需要两行:创建poolExecutor和map处理函数,一旦工作人员生成结果就收回结果。一旦processingFunction的第一次调用返回并继续进行直到它们全部完成,结果就会立即开始 - 此时for循环结束。

2 个答案:

答案 0 :(得分:6)

与Scala中使用并行集合相比,你的样板更少。

myParameters.par.map(x => f(x))
如果你想要默认的线程数(与核心数相同),

就可以了。

如果你坚持设定工人数量,你可以这样:

import scala.collection.parallel._
import scala.concurrent.forkjoin._

val temp = myParameters.par
temp.tasksupport = new ForkJoinTaskSupport(new ForkJoinPool(5))
temp.map(x => f(x))

返回时间的确切细节是不同的,但是您可以将所需的机器放入f(x)(即计算并对结果执行某些操作),这样可以满足您的需求。

一般来说,仅仅将结果显示为已完成是不够的;然后你需要处理它们,也许是分叉它们,收集它们等等。如果你想这样做一般,Akka Streams(跟随here的链接)接近1.0,将有助于生成复杂的图形并行处理。

答案 1 :(得分:0)

有一个Futures api允许你在线程池上运行工作单元(docs:http://docs.scala-lang.org/overviews/core/futures.html)和一个“parallell collections api”,你可以用它来对集合执行并行操作:{{ 3}}