Похищение параллельной работы, кажется, не крадет много работы

Идея состоит в том, чтобы запустить параллельную работу на 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 имеет около 20000 предметов. На обработку большинства предметов уходит 2-8 секунд, и только около 200 из них занимают больше времени, около 40 секунд.

Эта проблема:

Все работает хорошо, однако, аспект кражи работы, кажется, не работает хорошо. Вот ожидаемая общая загрузка ЦП (черный цвет) по сравнению с фактической нагрузкой (синий цвет) с течением времени:

Ожидаемая и фактическая рабочая нагрузка

Если посмотреть на активность процессора, становится ясно, что все меньше и меньше ядер используются по мере продвижения работы к концу. В течение последних 10 минут только 2 или 3 ядра все еще заняты последовательной обработкой десятков элементов, одно за другим.

Почему элементы, все еще находящиеся в очереди, не будут украдены другими свободными ядрами, даже при использовании ForkJoinPoolкакой должен быть кража работы?

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

1 ответ

Решение

Каждый рабочий поток имеет свою внутреннюю очередь задач, которая защищена от кражи работы из других потоков, чтобы ограничить взаимодействие между рабочими.

Это, вероятно, объясняет поведение, которое вы видите, особенно если появление длинного задания в вашем наборе предметов не случайно.

Другие вопросы по тегам