Fork / Join может парализовать вычисления. Это: дает вам постоянный выигрыш (разделите время на 4 на примере). И это ограничено реальными процессорами, которые у вас есть (например, 200 потоков будут использовать одни и те же 4 процессора).
В противоположность факториалу (типичный алгоритм) равен O(N!)
, что означает, что он очень очень быстро растет.
И если вы создаете новый форк для каждого шага, накладные расходы на разветвление и соединение компенсируют выигрыш от распараллеливания.
Поэтому важно попытаться вычислить факториал с помощью другого алгоритма, который не O(N!)
. Если вы применяете динамическое программирование (повторно используя промежуточные результаты), вы можете преобразовать его в O(N)
.
Я не знаю, какой алгоритм вы пытаетесь имитировать с помощью того, что я должен сделать, - это управлять матрицей или чем-то вроде вычислений для пар, чтобы использовать их повторно, когда они мне понадобятся во второй раз ...
Глядя на ваш код, я вижу, что выполнение каждого факторного метода провоцирует два дочерних выполнения: (p+q)/2,q
и p,(p+q)/2+1
... или что-то в этом роде. Если каждый метод факториала времени находит результат, сохраняет его на карте [Pair -> BigDecimal]
, вы можете запросить этот кеш в начале метода. Сделайте эту карту членом вашего класса (или передайте ее через аргументы), чтобы различные вызовы методов разделяли карту.
factorial(p,q) {
if (there is result for (p,q) in the map)
return it
else
{
normal computation (provokes two child invocations)
save result into cache
}
}