如何使用MPI for Python并行化遗传算法

这期内容当中小编将会给大家带来有关如何使用MPI for Python并行化遗传算法,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

正文

我们在用遗传算法优化目标函数的时候,函数通常都是高维函数,其导数一般比较难求取。这样我们的适应度函数计算通常都是比较费时的计算。

例如在使用遗传算法寻找最优结构时候通常需要调用量化软件进行第一性原理计算结构的total energy,这是非常费时的过程; 例如我们优化力场参数的时候,以力场计算出的能量同基准能量之前的误差作为适应度,也需要调用相应的力场程序获取总能量来求取,同样这个过程也是相对耗时的。

这就会导致一个问题,当我们的种群比较大的时候,我们需要利用适应度信息来产生下一代种群,这时候每一代繁殖的过程将会很耗时。但有幸的是,种群的选择交叉变异过程对于种群中的个体都是相互独立的过程,我们可以将这一部分进行并行处理来加速遗传算法的迭代。厦门叉车

将mpi4py的接口进一步封装

为了能让mpi的接口在GAFT中更方便的调用,我决定将mpi4py针对遗传算法中需要用的地方进行进一步封装,为此我单独写了个MPIUtil类, 详细代码参见gaft/mpiutil.py。

组内集合通信接口

由于本次并行化的任务是在种群繁衍时候进行的,因此我需要将上一代种群进行划分,划分成多个子部分,然后在每个进程中对划分好的子部分进行选择交叉变异等遗传操作。在最后将每个字部分得到的子种群进行收集合并。为此写了几个划分和收集的接口:

Python

def split_seq(self, sequence):

    '''

    Split the sequence according to rank and processor number.

    '''

    starts = [i for i in range(0, len(sequence), len(sequence)//self.size)]

    ends = starts[1: ] + [len(sequence)]

    start, end = list(zip(starts, ends))[self.rank]

 

    return sequence[start: end]

 

def split_size(self, size):

    '''

    Split a size number(int) to sub-size number.

    '''

    if size < self.size:

        warn_msg = ('Splitting size({}) is smaller than process ' +

                    'number({}), more processor would be ' +

                    'superflous').format(size, self.size)

        self._logger.warning(warn_msg)

        splited_sizes = [1]*size + [0]*(self.size – size)

    elif size % self.size != 0:

        residual = size % self.size

        splited_sizes = [size // self.size]*self.size

        for i in range(residual):

            splited_sizes[i] += 1

    else:

        splited_sizes = [size // self.size]*self.size

 

    return splited_sizes[self.rank]

 

def merge_seq(self, seq):

    '''

    Gather data in sub-process to root process.

    '''

    if self.size == 1:

        return seq

 

    mpi_comm = MPI.COMM_WORLD

    merged_seq= mpi_comm.allgather(seq)

    return list(chain(*merged_seq))

在遗传算法主循环中添加并行

主要在种群繁衍中对种群针对进程数进行划分然后并行进行遗传操作并合并子种群完成并行,代码改动很少。详见:https://github.com/PytLab/gaft/blob/master/gaft/engine.py#L67

Python

# Enter evolution iteration.for g in range(ng):    # Scatter jobs to all processes.    local_indvs = []    local_size = mpi.split_size(self.population.size // 2)
      # Fill the new population.    for _ in range(local_size):        # Select father and mother.        parents = self.selection.select(self.population, fitness=self.fitness)        # Crossover.        children = self.crossover.cross(*parents)        # Mutation.        children = [self.mutation.mutate(child) for child in children]        # Collect children.        local_indvs.extend(children)
      # Gather individuals from all processes.    indvs = mpi.merge_seq(local_indvs)    # The next generation.    self.population.individuals = indvs

下面我针对项目中的一维优化的例子进行并行加速测试来看看加速的效果。例子代码在/examples/ex01/

由于自己本子核心数量有限,我把gaft安装在实验室集群上使用MPI利用多核心进行并行计算一维优化,种群大小为50,代数为100,针对不同核心数可以得到不同的优化时间和加速比。

上述就是小编为大家分享的如何使用MPI for Python并行化遗传算法了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/200200.html

(0)
上一篇 2021年11月20日
下一篇 2021年11月20日

相关推荐

发表回复

登录后才能评论