Optimization OpenMDAO v0.13:仅当尝试并行运行优化时出错”;索引器:列表索引超出范围“;

Optimization OpenMDAO v0.13:仅当尝试并行运行优化时出错”;索引器:列表索引超出范围“;,optimization,parallel-processing,openmdao,Optimization,Parallel Processing,Openmdao,请参见底部添加的示例,它们比原始示例更精确地指出了错误 我一直在尝试让附加的代码并行运行。这段代码旨在模拟我希望在大型集群上运行的更大优化代码的结构。这里的错误出现在我们尝试过的几个不同的脚本中,其中一个脚本并行工作,除非连接到configure方法中从数组元素启动的循环中的组件。此示例在串行模式下运行良好,但当我运行命令mpirun-n4 python test2\u forParallel\u floats.py时,我得到以下输出: Traceback (most recent call l

请参见底部添加的示例,它们比原始示例更精确地指出了错误

我一直在尝试让附加的代码并行运行。这段代码旨在模拟我希望在大型集群上运行的更大优化代码的结构。这里的错误出现在我们尝试过的几个不同的脚本中,其中一个脚本并行工作,除非连接到configure方法中从数组元素启动的循环中的组件。此示例在串行模式下运行良好,但当我运行命令
mpirun-n4 python test2\u forParallel\u floats.py
时,我得到以下输出:

Traceback (most recent call last):
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/component.py", line 549, in run
    self._pre_execute()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/component.py", line 469, in _pre_execute
    self._setup()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/assembly.py", line 1701, in _setup
    self.setup_variables()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/assembly.py", line 1105, in setup_variables
    self._system.setup_variables()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 2387, in setup_variables
    super(DriverSystem, self).setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 2122, in setup_variables
    sub = list(self.local_subsystems())[0]
IndexError: list index out of range

Traceback (most recent call last):
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/component.py", line 549, in run
    self._pre_execute()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/component.py", line 469, in _pre_execute
    self._setup()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/assembly.py", line 1701, in _setup
Traceback (most recent call last):
  File "test2_forParallel_floats.py", line 170, in <module>
    test.run()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/component.py", line 549, in run
    self._pre_execute()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/component.py", line 469, in _pre_execute
    self._setup()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/assembly.py", line 1701, in _setup
    self.setup_variables()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/assembly.py", line 1105, in setup_variables
    self.setup_variables()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/assembly.py", line 1105, in setup_variables
    self._system.setup_variables()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 2387, in setup_variables
    super(DriverSystem, self).setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 2122, in setup_variables
    sub = list(self.local_subsystems())[0]
IndexError: list index out of range

    self._system.setup_variables()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 2387, in setup_variables
Traceback (most recent call last):
  File "test2_forParallel_floats.py", line 170, in <module>
    test.run()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/component.py", line 549, in run
    super(DriverSystem, self).setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    self._pre_execute()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/component.py", line 469, in _pre_execute
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    self._setup()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/assembly.py", line 1701, in _setup
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 2122, in setup_variables
    self.setup_variables()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/assembly.py", line 1105, in setup_variables
    self._system.setup_variables()
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 2387, in setup_variables
    super(DriverSystem, self).setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    sub = list(self.local_subsystems())[0]
IndexError: list index out of range
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 433, in setup_variables
    sub.setup_variables(resid_state_map)
  File "/Users/thomas95/OpenMDAO/openmdao-0.13.0/lib/python2.7/site-packages/openmdao.main-0.13.0-py2.7.egg/openmdao/main/systems.py", line 2122, in setup_variables
    sub = list(self.local_subsystems())[0]
IndexError: list index out of range

进一步的例子 此示例更好地显示了导致错误的原因。以下脚本对于默认驱动程序以串行或并行方式运行,但在使用SLSLQPdriver和pyOptDriver与SNOPT时失败。错误如下:

使用SLSQPdriver():
AttributeError:“SerialSystem”对象没有属性“options”

将pyOptDriver()与SNOPT:
索引器一起使用错误:索引0超出大小为0的轴1的界限

在x*=[0,0,0]处,结果应该是y*=0

编辑:我现在收到一个不同的SNOPT错误:
IOError:无法正确打开SNOPT_print.out,ierror=17
。我不知道是什么改变了


所以,我运行了你的模型,看到了和你一样的东西。我已经能够使它成功地与以下更改并行运行(我修改的代码如下)

  • MPI似乎不支持组件的有限差分。特别是,让它将模型分割成块进行有限差分会导致一些奇怪的并行错误。有两种方法可以解决这个问题。我选择为
    SimpleComp
    Summer
    组件定义分析导数,因为它们很简单。您还可以将整个模型的
    driver.gradient\u options.force\u fd
    设置为True以进行有限差分

  • 最初您使用的是PyOptDriver,但对于某些优化器,该驱动程序不能并行工作。具体地说,SNOPT会写出一个文本文件,因此您看到的
    ioError
    是当所有3个进程都试图写入同一个文件而无法写入时出现的。我们有一个并行版本的PyOptDriver(称为mdolab pyoptsparse),这就是我使用的。OpenMDAO包装器隐藏在pyMission存储库中:

    pyoptsparse可在此处找到:

    当你有这些,你可以提供SNOPT在适当的位置

  • 最后,我需要更严格地控制要并行放置哪些组件,因此我在工作流层次结构中添加了另一个级别。驱动程序
    parallel\u stuff
    只包含我们希望并行运行的SimpleComps。然后我将
    driver
    system\u type
    设置为serial,这样它就不会尝试在并行组中放入任何其他内容

  • 通过这些修复,我使您的模型优化并达到(0,0,0)


    谢谢你的回答,这些信息非常有用。
    from openmdao.main.api import Assembly, Component
    from openmdao.lib.datatypes.api import Float, Array, List
    from openmdao.lib.drivers.api import DOEdriver, SLSQPdriver, COBYLAdriver, CaseIteratorDriver
    from pyopt_driver.pyopt_driver import pyOptDriver
    
    import numpy as np
    
    
    class component1(Component):
    
        x = Float(iotype='in')
        y = Float(iotype='in')
        term1 = Float(iotype='out')
        a = Float(iotype='in', default_value=1)
    
        def execute(self):
            x = self.x
            a = self.a
    
            term1 = a*x**2
            self.term1 = term1
    
            print "In comp1", self.name, self.a, self.x, self.term1
    
        def list_deriv_vars(self):
            return ('x',), ('term1',)
    
        def provideJ(self):
    
            x = self.x
            a = self.a
            dterm1_dx = 2.*a*x
    
            J = np.array([[dterm1_dx]])
            # print 'In comp1, J = %s' % J
    
            return J
    
    
    class component2(Component):
    
        x = Float(iotype='in')
        y = Float(iotype='in')
        term1 = Float(iotype='in')
        f = Float(iotype='out')
        # q = Array(np.zeros(2), iotype='in', dtype='float')
    
        def execute(self):
    
            # y = self.y + self.q[0]
            # x = self.x + self.q[1]
    
            y = self.y
            x = self.x
    
            term1 = self.term1
            f = term1 + x + y**2
            # print 'in comp2 q = %s' % self.q
            self.f = f
            print "In comp2", self.name, self.x, self.y, self.term1, self.f
    
    
    
    class summer(Component):
    
    
        total = Float(iotype='out', desc='sum of all f values')
    
        def __init__(self, size):
            super(summer, self).__init__()
            self.size = size
    
            self.add('fs', Array(np.zeros(size), iotype='in', desc='f values from all cases'))
    
        def execute(self):
            self.total = sum(self.fs)
            print 'In summer, fs = %s and total = %s' % (self.fs, self.total)
    
    
    class assembly(Assembly):
    
        x = Float(iotype='in')
        y = Float(iotype='in')
        total = Float(iotype='out')
    
        def __init__(self, size):
    
            super(assembly, self).__init__()
    
            self.size = size
            for i in range(0, size):
                self.add('a_vals_%d' % i, Float(iotype='in'))
                # self.add('q_%d' % i, Array(np.zeros(2), iotype='in', dtype='float'))
                a = str()
                exec("a = self.a_vals_%d" % i)
                print 'in init, a_vals_%d = %s' % (i, a)
    
            self.add('fs', Array(np.zeros(size), iotype='out', dtype='float'))
            print 'in init, fs = %s' % self.fs
    
        def configure(self):
    
            self.add('driver', SLSQPdriver())
            # self.add('driver', pyOptDriver())
            # self.driver.optimizer = 'SNOPT'
            # self.driver.pyopt_diff = True
    
            #create this first, so we can connect to it
            self.add('summer', summer(size=self.size))
            self.connect('summer.total', 'total')
    
            for i in range(0, self.size):
                a = str()
                exec("a = self.a_vals_%d" % i)
                print 'in configure, a_vals_%d = %s' % (i, a)
    
    
            # create instances of components
            for i in range(0, self.size):
                c1 = self.add('comp1_%d' % i, component1())
                c1.missing_deriv_policy = 'assume_zero'
    
                c2 = self.add('comp2_%d'%i, component2())
                self.connect('a_vals_%d' % i, 'comp1_%d.a' % i)
                self.connect('x', ['comp1_%d.x' % i, 'comp2_%d.x' % i])
                self.connect('y', ['comp1_%d.y' % i, 'comp2_%d.y' % i])
                self.connect('comp1_%d.term1' % i, 'comp2_%d.term1' % i)
                # self.connect('q_%d' % i, 'comp2_%d.q' % i)
    
                self.connect('comp2_%d.f' % i, 'summer.fs[%d]' % i)
    
                self.driver.workflow.add(['comp1_%d' % i, 'comp2_%d' % i])
    
            # self.connect('summer.fs[:]', 'fs[:]')
            self.driver.workflow.add(['summer'])
    
            # set up main driver (optimizer)
            self.driver.iprint = 1
            self.driver.maxiter = 100
            self.driver.accuracy = 1.0e-6
            self.driver.add_parameter('x', low=-5., high=5.)
            self.driver.add_parameter('y', low=0., high=5.)
            # for i in range(0, self.size):
            #     self.driver.add_parameter('q_%d' % i, low=0., high=5.)
            self.driver.add_objective('summer.total')
    
    
    if __name__ == "__main__":
        """ the result should be -1 at (x, y) = (-0.5, 0) """
    
        import time
        from openmdao.main.api import set_as_top
        a_vals = np.array([1., 1., 1., 1.])
        test = set_as_top(assembly(size=len(a_vals)))
        # test.a_vals = a_vals
        # print 'in main, test.a_vals = %s, test.fs = %s' % (test.a_vals, test.fs)
        test.x = 2.
        test.y = 5
        # q = np.tile(np.arange(1., 3.), (4, 1))
        for i in range(0, len(a_vals)):
            exec('test.a_vals_%d = a_vals[%d]' % (i, i))
        #     exec('test.q_%d = q[%d]' % (i, i))
        #     exec('print test.q_%d' % i)
            a = str()
            exec("a = test.a_vals_%d" % i)
            print 'in main, a_vals_%d = %s' % (i, a)
    
        tt = time.time()
        test = set_as_top(test)
        test.run()
    
        print "Elapsed time: ", time.time()-tt, "seconds"
    
        print 'result = ', test.summer.total
        print '(x, y) = (%s, %s)' % (test.x, test.y)
        print 'fs = %s' % test.fs
        print test.fs
        # for i in range(0, len(a_vals)):
        #     exec('print test.q_%d' % i)
    
    import numpy as np
    import time
    
    from openmdao.main.api import Component, Assembly
    from openmdao.lib.datatypes.api import Float, Array
    from openmdao.lib.drivers.api import FixedPointIterator, SLSQPdriver, COBYLAdriver
    from pyopt_driver.pyopt_driver import pyOptDriver
    
    class SimpleComp(Component):
    
        x = Float(iotype="in")
        y = Float(iotype="out")
    
        def execute(self):
            # print 'print'
            print 'In SimpleComp, x = %s' % self.x
            # time.sleep(2) #slow things down to make the parallization more clear
    
            self.y = self.x*self.x
    
    class Summer(Component):
    
        def __init__(self, size):
            super(Summer, self).__init__()
    
            self.size = int(size)
            for i in xrange(size):
                self.add('y_%d'%i, Float(iotype="in"))
    
            self.add('tot', Float(iotype="out"))
    
        def execute(self):
            tot = 0
            for i in xrange(self.size):
                tot += getattr(self, 'y_%d'%i)
            self.tot = tot
    
    
    
    class Sim(Assembly):
    
        def __init__(self, size):
            super(Sim, self).__init__()
    
            # self.add('x', Array(np.zeros(size), dtype='float', iotype='in'))
            # self.add('x', Float(iotype='in'))
            for i in range(0, size):
                self.add('x_%d' % i, Float(iotype='in'))
    
        def configure(self):
    
            #you'll need one process per point
    
            # self.add('driver', SLSQPdriver())
            self.add('driver', pyOptDriver())
            self.driver.optimizer = 'SNOPT'
    
            self.add('summer', Summer(size))
            # print self.x
    
            for i in xrange(size):
                # print 'x = ', self.x[i]
                self.add('point_%d'%i, SimpleComp())
                self.connect('x_%d' % i, 'point_%d.x' % i)
                self.connect('point_%d.y'%i, 'summer.y_%d'%i)
                self.driver.workflow.add('point_%d'%i)
                self.driver.add_parameter('x_%d' % i, high=10, low=-10)
    
            self.driver.workflow.add('summer')
    
            self.driver.add_objective('summer.tot')
    
    
    if __name__ == "__main__":
        from openmdao.main.api import set_as_top
    
        size = 3
    
        x = np.arange(0, size)
        # x = 1.
        print x
    
        sim = set_as_top(Sim(size))
    
        for i in range(0, size):
            exec('sim.x_%d = x[%d]' % (i, i))
        st = time.time()
        sim.run()
    
        print "runtime: ", time.time() - st
    
        print 'y* = %s' % sim.summer.tot
    
    import numpy as np
    import time
    from openmdao.main.api import Component, Assembly, Driver
    from openmdao.lib.datatypes.api import Float, Array
    from openmdao.lib.drivers.api import FixedPointIterator, SLSQPdriver, COBYLAdriver
    from pyopt_driver.pyopt_driver import pyOptDriver
    from pyoptsparse_driver.pyoptsparse_driver import pyOptSparseDriver
    
    class SimpleComp(Component):
        x = Float(iotype="in")
        y = Float(iotype="out")
        def execute(self):
            # print 'print'
            print 'In SimpleComp, x = %s' % self.x
            # time.sleep(2) #slow things down to make the parallization more clear
            self.y = self.x*self.x
        def provideJ(self):
            J = np.zeros((1, 1))
            J[0][0] = 2.0*self.x
            return J
        def list_deriv_vars(self):
            return ('x', ), ('y', )
    
    class Summer(Component):
        def __init__(self, size):
            super(Summer, self).__init__()
            self.size = int(size)
            for i in xrange(size):
                self.add('y_%d'%i, Float(iotype="in"))
            self.add('tot', Float(iotype="out"))
        def execute(self):
            tot = 0
            for i in xrange(self.size):
                tot += getattr(self, 'y_%d'%i)
            self.tot = tot
        def provideJ(self):
            J = np.ones((1, self.size))
            return J
        def list_deriv_vars(self):
            inputs = ['y_%d'%i for i in range(self.size)]
            return inputs, ('tot', )
    
    class Sim(Assembly):
        def __init__(self, size):
            super(Sim, self).__init__()
            # self.add('x', Array(np.zeros(size), dtype='float', iotype='in'))
            # self.add('x', Float(iotype='in'))
            for i in range(0, size):
                self.add('x_%d' % i, Float(iotype='in'))
        def configure(self):
            #you'll need one process per point
            self.add('driver', pyOptSparseDriver())
            self.add('parallel_stuff', Driver())
            self.driver.optimizer = 'SNOPT'
            self.add('summer', Summer(size))
            # print self.x
            for i in xrange(size):
                # print 'x = ', self.x[i]
                self.add('point_%d'%i, SimpleComp())
                self.connect('x_%d' % i, 'point_%d.x' % i)
                self.connect('point_%d.y'%i, 'summer.y_%d'%i)
                self.parallel_stuff.workflow.add('point_%d'%i)
                self.driver.add_parameter('x_%d' % i, high=10, low=-10)
            self.driver.workflow.add(['parallel_stuff', 'summer'])
            self.driver.add_objective('summer.tot')
    
            # Don't try to parallelize anything except 'parallel_stuff'
            self.driver.system_type = 'serial'
    
    if __name__ == "__main__":
        from openmdao.main.api import set_as_top
        size = 2
        x = np.arange(0, size)
        # x = 1.
        print x
        sim = set_as_top(Sim(size))
        for i in range(0, size):
            exec('sim.x_%d = x[%d]' % (i, i))
        st = time.time()
        sim._setup()
    
        sim.run()
        print "runtime: ", time.time() - st
        print 'y* = %s' % sim.summer.tot