Я пробовал многопроцессорное программирование с помощью Python. Возьмите алгоритм разделения и покоя, например, Fibonacci
. Поток выполнения программы разветвляется как дерево и выполняется параллельно. Другими словами, мы имеем пример nested parallelism.Вложенный параллелизм в Python
Из Java я использовал шаблон threadpool для управления ресурсами, так как программа могла быстро разветвляться и создавать слишком много короткоживущих потоков. Один статический (общий) поток можно создать через ExecutorService
.
Ожидаю то же самое для Pool, но оказывается, что Pool object is not to be globally shared. Например, совместное использование пула с использованием multiprocessing.Manager.Namespace()
приведет к ошибке.
объекты бассейна не могут быть переданы между процессами или маринованные
У меня есть 2 части вопроса:
- Что я здесь отсутствует; почему не следует делиться пулом между процессами?
- Что такое шаблон для реализации вложенного параллелизма в Python? Если возможно, поддерживайте рекурсивную структуру, а не торгуйте ее для итерации.
from concurrent.futures import ThreadPoolExecutor
def fibonacci(n):
if n < 2:
return n
a = pool.submit(fibonacci, n - 1)
b = pool.submit(fibonacci, n - 2)
return a.result() + b.result()
def main():
global pool
N = int(10)
with ThreadPoolExecutor(2**N) as pool:
print(fibonacci(N))
main()
Java
public class FibTask implements Callable<Integer> {
public static ExecutorService pool = Executors.newCachedThreadPool();
int arg;
public FibTask(int n) {
this.arg= n;
}
@Override
public Integer call() throws Exception {
if (this.arg > 2) {
Future<Integer> left = pool.submit(new FibTask(arg - 1));
Future<Integer> right = pool.submit(new FibTask(arg - 2));
return left.get() + right.get();
} else {
return 1;
}
}
public static void main(String[] args) throws Exception {
Integer n = 14;
Callable<Integer> task = new FibTask(n);
Future<Integer> result =FibTask.pool.submit(task);
System.out.println(Integer.toString(result.get()));
FibTask.pool.shutdown();
}
}
Я не уверен, если это имеет значение здесь, но я не обращая внимания на разницу между "процессом" и "нити"; для меня они оба означают «виртуализированный процессор». Я понимаю, что цель пула заключается в совместном использовании «пула» или ресурсов. Запуск задач может сделать запрос в пул. По мере выполнения параллельных задач в других потоках эти потоки могут быть восстановлены и назначены для новых задач. Мне не имеет смысла запрещать совместное использование пула, чтобы каждый поток должен создавать свой собственный новый пул, поскольку это, казалось бы, превзошло цель пула потоков.
Зачем вам это нужно для общего доступа?Разве вы не можете содержать все это внутри одного пространства имен/класса? –
@InbarRose Проблема в том, что в рекурсивной функции, которая выполняет рекурсивный вызов внутри другого процесса, пул разветвляется и также вызывается подпроцессом. Это вызывает проблемы с очередями, следовательно, это не работает. В любом случае я хотел бы подчеркнуть, что в Java вы используете * threads *. С потоками нет никаких проблем, так как нет разметки объекта пула. Я считаю, что использование пула процессов в Java приведет к более или менее одинаковому поведению. – Bakuriu
@InbarRose Я также пробовал содержать «пул» как экземпляр класса и статическую переменную, но все равно доходил до проблемы с проблемой. Например, с пулом и рекурсивными вызовами, содержащимися в пределах одного класса, но это все равно приводит к одной и той же проблеме:> объекты пула не могут быть переданы между процессами ... –