Почему повышенные имена недопустимы при параллельной работе?
Я пытаюсь запустить простую математическую задачу параллельно в OpenMDAO 2.5.0. Проблема заключается в адаптированной версии примера в документации OpenMDAO, которая находится здесь: http://openmdao.org/twodocs/versions/latest/features/core_features/grouping_components/parallel_group.html. Он имеет некоторые дополнительные компоненты и соединения и использует рекламные акции вместо соединений.
from openmdao.api import Problem, IndepVarComp, ParallelGroup, ExecComp, Group, NonlinearBlockGS
prob = Problem()
model = prob.model
model.add_subsystem('p1', IndepVarComp('x1', 1.0), promotes=['x1'])
model.add_subsystem('p2', IndepVarComp('x2', 1.0), promotes=['x2'])
cycle = model.add_subsystem('cycle', Group(), promotes=['*'])
parallel = cycle.add_subsystem('parallel', ParallelGroup(), promotes=['*'])
parallel.add_subsystem('c1', ExecComp(['y1=(-2.0*x1+z)/3']), promotes=['x1', 'y1', 'z'])
parallel.add_subsystem('c2', ExecComp(['y2=(5.0*x2-z)/6']), promotes=['x2', 'y2', 'z'])
cycle.add_subsystem('c3', ExecComp(['z=(3.0*y1+7.0*y2)/10']), promotes=['y1', 'y2', 'z'])
model.add_subsystem('c4', ExecComp(['z2 = y1+y2']), promotes=['z2', 'y1', 'y2'])
cycle.nonlinear_solver = NonlinearBlockGS()
prob.setup(mode='fwd')
prob.set_solver_print(level=2)
prob.run_model()
print(prob['z2'])
print(prob['z'])
print(prob['y1'])
print(prob['y2'])
Когда я запускаю этот код последовательно, он работает, как и ожидалось, без ошибок.
Однако, когда я запускаю этот код параллельно с:
mpirun -n 2 python Test.py
Я получаю эту ошибку для первого процесса:
RuntimeError: The promoted name y1 is invalid because it refers to multiple inputs: [cycle.c3.y1 ,c4.y1]. Access the value from the connected output variable cycle.parallel.c1.y1 instead.
и эта ошибка для второго процесса:
RuntimeError: The promoted name y2 is invalid because it refers to multiple inputs: [cycle.c3.y2 ,c4.y2]. Access the value from the connected output variable cycle.parallel.c2.y2 instead.
Итак, мой вопрос: почему этот пример выдает ошибку в именах продвижений при параллельной работе, когда он работает без проблем в серии? Разрешено ли использовать соединения только при параллельной работе, или все переменные тоже в порядке?
1 ответ
Начиная с OpenMDAO V2.5, вы должны быть немного осторожны при параллельном доступе к проблемным переменным.
Если вы посмотрите на полный трек стека вашей модели, вы увидите, что ошибка выдается прямо в конце, когда вы вызываете
print(prob['y1'])
print(prob['y2'])
Здесь происходит то, что вы настроили модель так, чтобы y1
существует только на proc 0 и y2
существует только в proc 1. Затем вы пытаетесь получить значения, которые не существуют в этом proc, и вы получаете (по общему признанию, не очень ясную) ошибку.
Вы можете исправить это с помощью следующих незначительных изменений в вашем скрипте:
from openmdao.api import Problem, IndepVarComp, ParallelGroup, ExecComp, Group, NonlinearBlockJac
prob = Problem()
model = prob.model
model.add_subsystem('p1', IndepVarComp('x1', 1.0), promotes=['x1'])
model.add_subsystem('p2', IndepVarComp('x2', 1.0), promotes=['x2'])
cycle = model.add_subsystem('cycle', Group(), promotes=['*'])
parallel = cycle.add_subsystem('parallel', ParallelGroup(), promotes=['*'])
parallel.add_subsystem('c1', ExecComp(['y1=(-2.0*x1+z)/3']), promotes=['x1', 'y1', 'z'])
parallel.add_subsystem('c2', ExecComp(['y2=(5.0*x2-z)/6']), promotes=['x2', 'y2', 'z'])
cycle.add_subsystem('c3', ExecComp(['z=(3.0*y1+7.0*y2)/10']), promotes=['y1', 'y2', 'z'])
model.add_subsystem('c4', ExecComp(['z2 = y1+y2']), promotes=['z2', 'y1', 'y2'])
cycle.nonlinear_solver = NonlinearBlockJac()
prob.setup(mode='fwd')
prob.set_solver_print(level=2)
prob.run_model()
print(prob['z2'])
print(prob['z'])
if prob.model.comm.rank == 0:
print(prob['y1'])
if prob.model.comm.rank == 0:
print(prob['y2'])
Есть несколько мелких проблем с этим. 1) это означает, что ваш скрипт теперь отличается для последовательного и параллельного. 2) Это раздражает. Итак, мы работаем над исправлением, которое позволит вещам работать более чисто, автоматически выполняя трансляцию MPI, когда вы пытаетесь получить значение, которое нет в вашем процессе. Это будет выпущено в V2.6.
Еще одна маленькая заметка. Я изменил вам NL решатель на NonLinearBlockJac. Это для блока Якоби, который предназначен для параллельной работы. Вы также можете использовать решатель Ньютона параллельно. Решатель Гаусса-Зайделя на самом деле не позволит вам получить параллельное ускорение.