Python遗传优化多进程全局常量变量,如何加速?

Python遗传优化多进程全局常量变量,如何加速?,python,performance,multiprocessing,genetic-algorithm,deap,Python,Performance,Multiprocessing,Genetic Algorithm,Deap,我正在编写一个基于Python2.7包的遗传优化算法(目标是很快迁移到Python3)。由于这是一个相当繁重的过程,优化的某些部分使用多处理包进行处理。以下是我的课程概要: 配置被读入并保存在config对象中 进行一些额外的预计算,并将其保存在config对象中 优化开始(随机初始化总体并应用突变、交叉以找到更好的解决方案),部分优化(评估函数)在多处理中执行 结果将被保存 对于求值函数,我们需要访问config对象的某些部分(在第2阶段之后保持不变)。因此,我们使用一个全局(常量)变量使不同

我正在编写一个基于Python2.7包的遗传优化算法(目标是很快迁移到Python3)。由于这是一个相当繁重的过程,优化的某些部分使用多处理包进行处理。以下是我的课程概要:

  • 配置被读入并保存在
    config
    对象中
  • 进行一些额外的预计算,并将其保存在
    config
    对象中
  • 优化开始(随机初始化总体并应用突变、交叉以找到更好的解决方案),部分优化(评估函数)在多处理中执行
  • 结果将被保存
  • 对于求值函数,我们需要访问
    config
    对象的某些部分(在第2阶段之后保持不变)。因此,我们使用一个全局(常量)变量使不同的内核可以访问它:

    来自deap导入库
    导入多处理
    toolbox=base.toolbox()
    def评估(ind):
    #使用配置对象计算求值
    返回(obj1、obj2)
    工具箱.寄存器('evaluate',evaluate)
    def初始池全局变量(自配置):
    全局配置
    配置=\u配置
    ...
    #设置多处理
    pool=multiprocessing.pool(进程=72,初始值设定项=self.init\u pool\u global\u vars,
    initargs=[config])
    toolbox.register('map',pool.map\u async)
    ...
    当tic
    我们基本上进行不同的迭代(大循环),直到达到最大时间。我注意到,如果我将config对象变大(即,向其添加大属性,如大numpy数组),即使代码仍然相同,它的运行速度也会慢得多(相同时间跨度内的迭代次数更少)。因此,我想我会创建一个特定的
    config\u multiprocessing
    对象,它只包含多处理部分所需的属性,并将其作为全局变量传递,但是当我在3个核上运行它时,它比在大
    config
    对象上运行的速度慢,在72个核上运行时,它稍微快一些,但不会太多

    在启动多处理循环之前,我应该如何确保我的循环不会因配置对象或任何其他数据操作而在速度上受到影响


    在云中Linux虚拟机上的Linux docker映像中运行。

    joblib
    包设计用于处理大型numpy阵列要分发给工作人员的情况。如果您将共享内存中的数据视为“只读”数据(如您在场景中所描述的),这一点尤其有用。您还可以创建可写共享内存

    您的代码可能类似于:

    
    import os
    
    import numpy as np
    from joblib import Parallel, delayed
    from joblib import dump, load
    
    folder = './joblib_memmap'
    try:
        os.mkdir(folder)
    except FileExistsError:
        pass
    
    def evaluate(ind, data):
        # compute evaluation using shared memory data
        return(obj1, obj2)
    
    # just used to initialize memory mapped data
    def init_memmap_data(original_data):
        data_filename_memmap = os.path.join(folder, 'data_memmap')
        dump(original_data, data_filename_memmap)
        shared_data = load(data_filename_memmap, mmap_mode='r')
        return shared_data
    
    ...
    # however you set up indices needs to be changed here
    indexes = range(10)  
    
    # however you load your numpy data needs to be done here
    shared_data = init_memmap_data(numpy_array_to_share)  
    
    # change n_jobs as appropriate
    results = Parallel(n_jobs=2)(delayed(evaluate)(ind, shared_data) for ind in indexes)  
    
    # get index of the maximum as the "best" individual
    best_fit_individual = indexes[results.argmax()]
    

    此外,
    joblib
    支持一种可能比基于进程的更快的方法。使用joblib测试这两个选项将很容易。

    您是否在windows上运行?如果是这样,请看一看否。我正在云中Linux VM上的Linux docker映像中运行它,但我不能这样做,因为我想调用
    多处理.Pool
    。一开始,我还没有创建我的配置对象,因此我无法使用该对象作为全局变量初始化不同的执行器(与开始时一样,它还不存在或尚未完成)由
    池创建的所有子进程将继承状态(内存)从被pickle用于传输的父进程。因此,如果将
    config
    对象变大,则需要执行更多的pickle操作,并且需要复制更多的内存。由于子进程仍然继承全局状态,因此不必使用额外的初始值设定函数。当创建特定的
    config\u多进程时假设源于
    config
    ,在生成池之前您是否
    del-config
    ?因为如果不是,则两个对象
    config\u multiprocessing
    config
    都将复制到子进程。这与我不将config传递到多处理池时的情况不同(即
    pool=multiprocessing.pool(processs=config.nprocess)
    )我有一个错误,说没有定义config
    NameError:global name'config'没有定义
    我在linux docker容器中运行,因此池创建的子进程不会继承父进程的状态!感谢@hume的回答,但是我不仅有numpy数组,还有其他类型的对象(词汇表、对象嵌套列表、带浮动的列表等)我想这仍然有效?我还没有完全理解的是使用
    joblib
    multiprocessing
    相比有什么优势?您可以创建这些配置项并将其传递给函数,甚至在定义函数时将其包含在函数中,它将像多处理一样工作。正如您所指出的,有一个用于将实际数据分发给每个工作进程,因为实际数据更大。
    joblib
    的优点是,如上所述使用时,它不会将数据分发给每个工作进程。相反,它会将数据加载到内存中一次,并为每个工作进程提供一个引用,供其用于计算。我已经介绍了ted它,但我得到一个错误,说
    AttributeError:无法在
    但是我无法从deap中更改Individual,因为这是我用于或者是优化的遗传算法,当按照建议将后端更改为多处理时,当它想要评估函数时,我会遇到另一个错误