【问题标题】:Implementing Multiprocessing with the same Function in While Loop在 While 循环中使用相同的函数实现多处理
【发布时间】:2021-03-01 00:13:52
【问题描述】:

我已经在 Python 3.8 中实现了进化算法流程,并且正在尝试优化/减少其运行时间。由于对有效解决方案的严格限制,生成有效染色体可能需要几分钟。为了避免花费数小时来生成初始种群,我想使用 Multiprocessing 一次生成多个。

我此时的代码是:

populationCount = 500

def readDistanceMatrix():
    # code removed

def generateAvailableValues():
    # code removed

def generateAvailableValuesPerColumn():
    # code removed

def generateScheduleTemplate():
    # code removed

def generateChromosome():
    # code removed

if __name__ == '__main__':
    # Data type = DataFrame
    distanceMatrix = readDistanceMatrix()
    
    # Data type = List of Integers
    availableValues = generateAvailableValues()

    # Data type = List containing Lists of Integers
    availableValuesPerColumn = generateAvailableValuesPerColumn(availableValues)
        
    # Data type = DataFrame
    scheduleTemplate = generateScheduleTemplate(distanceMatrix)
    
    # Data type = List containing custom class (with Integer and DataFrame)
    population = []
    while len(population) < populationCount:
        chrmSolution = generateChromosome(availableValuesPerColumn, scheduleTemplate, distanceMatrix)
        population.append(chrmSolution)

人口列表在最后用while循环填充。我想用一个多处理解决方案替换 while 循环,该解决方案最多可以使用预设数量的核心。例如:

population = []
availableCores = 6 
while len(population) < populationCount:
    while usedCores < availableCores:
        # start generating another chromosome as 'chrmSolution'
    population.append(chrmSolution)

但是,在阅读和观看了数小时的教程之后,我无法启动并运行循环。我该怎么做呢?

【问题讨论】:

  • 您对多处理进行了哪些尝试,您在哪里卡住了?对于multiprocessing.Pool,这通常听起来像是一个很好的应用程序
  • 嗨亚伦,感谢您的回复。我能够实现与您在下面显示的非常相似的东西,并且经过一些调整后效果很好。谢谢老兄。

标签: python python-3.x multiprocessing evolutionary-algorithm


【解决方案1】:

听起来简单的multiprocessing.Pool 应该可以解决问题,或者至少是一个开始的地方。下面是一个简单的例子:

from multiprocessing import Pool, cpu_count

child_globals = {} #mutable object at the `module` level acts as container for globals (constants)

if __name__ == '__main__':
    # ...
    
    def init_child(availableValuesPerColumn, scheduleTemplate, distanceMatrix):
        #passing variables to the child process every time is inefficient if they're
        #  constant, so instead pass them to the initialization function, and let
        #  each child re-use them each time generateChromosome is called
        child_globals['availableValuesPerColumn'] = availableValuesPerColumn
        child_globals['scheduleTemplate'] = scheduleTemplate
        child_globals['distanceMatrix'] = distanceMatrix
        
    def child_work(i):
        #child_work simply wraps generateChromosome with inputs, and throws out dummy `i` from `range()`
        return generateChromosome(child_globals['availableValuesPerColumn'],
                                  child_globals['scheduleTemplate'],
                                  child_globals['distanceMatrix'])
    with Pool(cpu_count(), 
              initializer=init_child, #init function to stuff some constants into the child's global context
              initargs=(availableValuesPerColumn, scheduleTemplate, distanceMatrix)) as p:
        #imap_unordered doesn't make child processes wait to ensure order is preserved,
        #  so it keeps the cpu busy more often. it returns a generator, so we use list()
        #  to store the results into a list.
        population = list(p.imap_unordered(child_work, range(populationCount)))

【讨论】:

    猜你喜欢
    • 2020-12-24
    • 2018-09-08
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 2014-11-11
    • 1970-01-01
    相关资源
    最近更新 更多