Похищение параллельной работы, кажется, не крадет много работы
Идея состоит в том, чтобы запустить параллельную работу на 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 ответ
Каждый рабочий поток имеет свою внутреннюю очередь задач, которая защищена от кражи работы из других потоков, чтобы ограничить взаимодействие между рабочими.
Это, вероятно, объясняет поведение, которое вы видите, особенно если появление длинного задания в вашем наборе предметов не случайно.