窃取工作的并行工作似乎并没有窃取太多工作

Work-stealing parallel job doesn't seem to steal much work

想法是 运行 96 核机器上的并行作业,窃取工作 ForkJoinPool

下面是我目前使用的代码:

import scala.collection.parallel.ForkJoinTaskSupport
import scala.concurrent.forkjoin.ForkJoinPool

val sequence: ParSeq[Item] = getItems().par
sequence.tasksupport = new ForkJoinTaskSupport(new ForkJoinPool())
val results = for {
  item <- sequence
  res   = doSomethingWith(item)
} yield res

这里,sequence 有大约 20,000 项。大多数项目需要 2-8 秒来处理,只有大约 200 个需要更长的时间,大约 40 秒。

问题:

一切运行都很好,但是,工作窃取方面似乎效果不佳。以下是随时间变化的预期总 CPU 负载(黑色)与实际负载(蓝色)的比较:

查看 CPU activity 时,很明显随着作业的进行,使用的核心越来越少。最近10分钟,只有2、3个核心还在忙着处理几十个item,一个接一个。

为什么仍在队列中的项目不会被其他空闲核心窃取,即使使用 ForkJoinPool,这应该是工作窃取?

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html

每个工作线程都有其内部任务队列,可以防止从其他线程窃取工作以限制工作线程之间的交互。

这可能解释了您所看到的行为,尤其是如果您的项目集中出现的长任务不是随机的。