在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循环结束。
答案 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}}