Я пытаюсь решить простую математическую задачу параллельно в 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.
Итак, мой вопрос: почему этот пример дает ошибку в именах промоакций при параллельной работе, а при последовательной работе без проблем? Разрешено ли использовать соединения только при параллельной работе, или можно также использовать повышенные переменные?
Начиная с OpenMDAO V2.5, вы должны быть немного осторожны при параллельном доступе к проблемным переменным.
Если вы посмотрите на полную дорожку стека вашей модели, вы увидите, что ошибка возникает в самом конце, когда вы вызываете
print(prob['y1'])
print(prob['y2'])
Здесь происходит то, что вы настроили модель так, что y1
существует только в процедуре 0, а y2
существует только в процедуре 1. Затем вы пытаетесь получить значения, которых нет в этой процедуре, и вы получаете (по общему признанию, не очень ясно) ошибка.
Вы можете исправить это с помощью следующих незначительных изменений в вашем скрипте:
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 на НелинейныйБлокЖак. Это для Block Jacobi, который предназначен для параллельной работы. Вы также можете использовать решатель Ньютон параллельно. Решатель Гаусса-Зейделя фактически не позволит вам получить параллельное ускорение.