Multithreading Scala—在多线程内工作的最佳API

Multithreading Scala—在多线程内工作的最佳API,multithreading,scala,multiprocessing,Multithreading,Scala,Multiprocessing,在Python中,我使用了一个名为futures的库,它允许我用一个由N个工作进程组成的池以简洁明了的方式进行处理: schedulerQ=[] 对于在…: 工作参数=…#调用processingFunction(workParam)的参数 schedulerQ.append(工作参数) 使用futures.ProcessPoolExecutor(max_workers=5)作为执行器:#5个CPU 对于executor.map(processingFunction,schedulerQ)中的r

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

schedulerQ=[]
对于在…:
工作参数=…#调用processingFunction(workParam)的参数
schedulerQ.append(工作参数)
使用futures.ProcessPoolExecutor(max_workers=5)作为执行器:#5个CPU
对于executor.map(processingFunction,schedulerQ)中的retValue:
打印“收到的结果”,返回值
(处理函数受CPU限制,因此这里没有异步机器的意义-这是关于普通的旧算术计算)

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

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


问题的关键部分是JVM世界中是否有任何API像上面看到的Python
futures
一样清晰的东西。。。我认为这是我见过的最好的SMPAPI之一——准备一个包含所有调用的函数参数的列表,然后只有两行:创建poolExecutor和
map
处理函数,在工作人员生成结果后立即返回结果。当第一次调用
processingFunction
返回结果时,结果就开始出现,并一直出现,直到它们全部完成为止-此时for循环结束。

有一个Futures api,允许您在线程池(docs:)和“Parallel collections api”上运行工作单元您可以使用它对集合执行并行操作:

有一个Futures api允许您在线程池(docs:)上运行工作单元,还有一个“parallel collections api”可以用于对集合执行并行操作:

与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(遵循中的链接)接近1.0,将有助于生成复杂的并行处理图。

与在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(遵循中的链接)已接近1.0,将有助于生成并行处理的复杂图形。

非常好-谢谢!是否有相应的多处理解决方案,或者这只是关于多线程的吗?如果我在一系列中加入两个代码> PAR.MAP.<代码>,第二个会在第一个出现的时候开始工作吗?如果我这样做:<代码>某个Work.Par .map(x= > f1(x)).PAR .map(x=>f2(x))< /> >第一个<代码> map <代码>等待,直到所有的结果都在“第二个”之前被计算,或者它们一起异步运行吗?简单地说,
f2
是否会在
f1
的第一个成功结果可用时被调用,或者是否会等到
someWorkQ
的所有元素都由
f1
处理?@ttsiodras-您无需重复
par
。然而,不管你是否这样做,它都将等待第一张地图完全完成,然后你才能看到第二张地图。所以你需要<代码>某个工作。PAR。map {x= > Valy=f1(x);f2(y)},然后你会强制执行< <代码> f2>代码>发生在<代码> f1 < /代码>之后。如果你想要更复杂的东西,Akka Streams就是为此而设计的。(很好地处理线性情况,但也处理更复杂的分支和合并情况。)非常好-谢谢!是否有相应的多处理解决方案,或者这只是关于多线程的吗?如果我在一系列中加入两个代码> PAR.MAP.<代码>,第二个会在第一个出现的时候开始工作吗?如果我这样做:<代码>某个Work.Par .map(x= > f1(x)).PAR .map(x=>f2(x))< /> >第一个<代码> map <代码>等待,直到所有的结果都在“第二个”之前被计算,或者它们一起异步运行吗?简单地说,
f2
是否会在
f1
的第一个成功结果可用时被调用,或者是否会等到
someWorkQ
的所有元素都由
f1
处理?@ttsiodras-您无需重复
par
。然而,不管你是否这样做,它都将等待