Python 将多进程池包装到循环内(进程之间的共享内存)
我正在使用Python包“deap”用遗传算法解决一些多目标优化问题。这些函数可能非常昂贵,而且由于遗传算法的进化性质,它很快就会复合。现在这个包确实有一些支持,允许进化计算与多进程并行 但是,我想更进一步,多次运行优化,在一些优化参数上使用不同的值。例如,我可能想用不同的权重值来解决优化问题 对于循环来说,这似乎是一个非常自然的情况,但问题是这些参数必须在程序的全局范围内定义(即,在“main”函数之上),以便所有子进程都知道这些参数。下面是一些伪代码:Python 将多进程池包装到循环内(进程之间的共享内存),python,multiprocessing,python-multiprocessing,Python,Multiprocessing,Python Multiprocessing,我正在使用Python包“deap”用遗传算法解决一些多目标优化问题。这些函数可能非常昂贵,而且由于遗传算法的进化性质,它很快就会复合。现在这个包确实有一些支持,允许进化计算与多进程并行 但是,我想更进一步,多次运行优化,在一些优化参数上使用不同的值。例如,我可能想用不同的权重值来解决优化问题 对于循环来说,这似乎是一个非常自然的情况,但问题是这些参数必须在程序的全局范围内定义(即,在“main”函数之上),以便所有子进程都知道这些参数。下面是一些伪代码: # define deap param
# define deap parameters - have to be in the global scope
toolbox = base.Toolbox()
history = tools.History()
weights = [1, 1, -1] # This is primarily what I want to vary
creator.create("Fitness",base.Fitness, weights=weights)
creator.create("Individual", np.ndarray, fitness=creator.Fitness)
def main():
# run GA to solve multiobjective optimization problem
return my_optimized_values
if __name__=='__main__':
## What I'd like to do but can't ##
## all_weights = list(itertools.product([1, -1],repeat=3))
## for combo in all_weights:
## weights = combo
##
pool = multiprocessing.Pool(processes=6)
# This can be down here, and it distributes the GA computations to a pool of workers
toolbox.register("map",pool.map)
my_values = main()
我已经研究了各种可能性,比如multiprocessing.Value、multiprocessing的pathos fork以及其他,但是最终,读取单个类的子进程总是会出现问题
我已经在deap用户组中提出了这个问题,但它的社区规模远没有deap用户组那么大。另外,在我看来,这更像是一个一般的概念性Python问题,而不是deap的具体问题。我目前解决这个问题的方法就是多次运行代码,每次都更改一些参数定义。至少这样,GA计算仍然是并行的,但它确实需要更多的人工干预
非常感谢您的任何建议 使用
初始值设定项
/initargs
关键字参数为每次运行时需要更改的全局变量传递不同的值。初始值设定项
函数启动后,将使用initargs
作为其参数调用池
中每个工作进程。您可以在那里将全局变量设置为所需的值,在池的生命周期内,它们将在每个子级中正确设置
您需要为每次运行创建不同的池
,但这应该不是问题:
toolbox = base.Toolbox()
history = tools.History()
weights = None # We'll set this in the children later.
def init(_weights):
# This will run in each child process.
global weights
weights = _weights
creator.create("Fitness",base.Fitness, weights=weights)
creator.create("Individual", np.ndarray, fitness=creator.Fitness)
if __name__=='__main__':
all_weights = list(itertools.product([1, -1],repeat=3))
for combo in all_weights:
weights = combo
pool = multiprocessing.Pool(processes=6, initializer=init, initargs=(weights,))
toolbox.register("map",pool.map)
my_values = main()
pool.close()
pool.join()
我也对DEAP对全局范围的使用感到不舒服,我想我有一个替代的解决方案 每个循环迭代可以导入每个模块的不同版本,从而避免对全局范围的依赖
this_random = importlib.import_module("random")
this_creator = importlib.import_module("deap.creator")
this_algorithms = importlib.import_module("deap.algorithms")
this_base = importlib.import_module("deap.base")
this_tools = importlib.import_module("deap.tools")
据我所知,这似乎与多处理有关
例如,这里是DEAP的onemax_mp.py版本,它避免将任何DEAP文件放入全局范围。我在\uuuuu main\uuuu
中包含了一个循环,用于更改每次迭代的权重。(第一次最大化一个数,第二次最小化。)多处理一切正常
#!/usr/bin/env python2.7
# This file is part of DEAP.
#
# DEAP is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
#
# DEAP is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with DEAP. If not, see <http://www.gnu.org/licenses/>.
import array
import multiprocessing
import sys
if sys.version_info < (2, 7):
print("mpga_onemax example requires Python >= 2.7.")
exit(1)
import numpy
import importlib
def evalOneMax(individual):
return sum(individual),
def do_onemax_mp(weights, random_seed=None):
""" Run the onemax problem with the given weights and random seed. """
# create local copies of each module
this_random = importlib.import_module("random")
this_creator = importlib.import_module("deap.creator")
this_algorithms = importlib.import_module("deap.algorithms")
this_base = importlib.import_module("deap.base")
this_tools = importlib.import_module("deap.tools")
# hoisted from global scope
this_creator.create("FitnessMax", this_base.Fitness, weights=weights)
this_creator.create("Individual", array.array, typecode='b',
fitness=this_creator.FitnessMax)
this_toolbox = this_base.Toolbox()
this_toolbox.register("attr_bool", this_random.randint, 0, 1)
this_toolbox.register("individual", this_tools.initRepeat,
this_creator.Individual, this_toolbox.attr_bool, 100)
this_toolbox.register("population", this_tools.initRepeat, list,
this_toolbox.individual)
this_toolbox.register("evaluate", evalOneMax)
this_toolbox.register("mate", this_tools.cxTwoPoint)
this_toolbox.register("mutate", this_tools.mutFlipBit, indpb=0.05)
this_toolbox.register("select", this_tools.selTournament, tournsize=3)
# hoisted from __main__
this_random.seed(random_seed)
pool = multiprocessing.Pool(processes=4)
this_toolbox.register("map", pool.map)
pop = this_toolbox.population(n=300)
hof = this_tools.HallOfFame(1)
this_stats = this_tools.Statistics(lambda ind: ind.fitness.values)
this_stats.register("avg", numpy.mean)
this_stats.register("std", numpy.std)
this_stats.register("min", numpy.min)
this_stats.register("max", numpy.max)
this_algorithms.eaSimple(pop, this_toolbox, cxpb=0.5, mutpb=0.2, ngen=40,
stats=this_stats, halloffame=hof)
pool.close()
if __name__ == "__main__":
for tgt_weights in ((1.0,), (-1.0,)):
do_onemax_mp(tgt_weights)
#/usr/bin/env python2.7
#此文件是DEAP的一部分。
#
#DEAP是自由软件:您可以重新发布和/或修改它
#根据GNU Lesser通用公共许可证的条款
由自由软件基金会发布的版本3
#许可证,或(由您选择)任何更高版本。
#
#分发DEAP的目的是希望它有用,
#但无任何保证;甚至没有任何关于
#适销性或适合某一特定目的。见
#GNU Lesser通用公共许可证了解更多详细信息。
#
#您应该已经收到GNU Lesser General Public的副本
#与DEAP一起获得许可证。如果没有,请参阅。
导入数组
导入多处理
导入系统
如果系统版本信息<(2,7):
打印(“mpga_onemax示例需要Python>=2.7。”)
出口(1)
进口numpy
导入导入库
def evalOneMax(个人):
回报金额(个人),
def do_onemax_mp(权重,随机种子=无):
“”“使用给定的权重和随机种子运行onemax问题。”“”
#创建每个模块的本地副本
此\u random=importlib.import\u模块(“随机”)
此\u创建者=导入lib.import\u模块(“deap.creator”)
此算法=导入lib.import模块(“deap.algorithms”)
此基础=importlib.import\u模块(“deap.base”)
此工具=导入lib.import模块(“deap.tools”)
#吊离全球范围
此_creator.create(“FitnessMax”,此_base.Fitness,权重=权重)
此_creator.create(“个人”,array.array,typecode='b',
fitness=此_creator.FitnessMax)
this_toolbox=this_base.toolbox()
此\u toolbox.register(“attr\u bool”,this\u random.randint,0,1)
此_toolbox.register(“个人”),此_tools.initRepeat,
此_creator.personal,此_toolbox.attr_bool,100)
这个_toolbox.register(“填充”),这个_tools.initRepeat,list,
这是(个人)
这个工具箱。注册(“评估”,evalOneMax)
此\u toolbox.register(“mate”,此\u tools.cxTwoPoint)
此\u toolbox.register(“mutate”,此\u tools.mutfipbit,indpb=0.05)
此_toolbox.register(“选择”,此_tools.selTournament,tournsize=3)
#从主管道提升__
此\u random.seed(随机\u seed)
池=多处理。池(进程=4)
此\u toolbox.register(“map”,pool.map)
pop=该工具箱。人口(n=300)
hof=此工具的HallOfFame(1)
this_stats=this_tools.Statistics(lambda ind:ind.fitness.values)
此统计寄存器(“平均值”,numpy.mean)
此统计寄存器(“标准”,numpy.std)
此统计寄存器(“min”,numpy.min)
此统计寄存器(“max”,numpy.max)
这个算法.eaSimple(流行,这个工具箱,cxpb=0.5,mutpb=0.2,ngen=40,
统计数据=这(统计数据,halloffame=hof)
pool.close()
如果名称=“\uuuuu main\uuuuuuuu”:
对于tgt_重量单位((1.0,),(-1.0,):
do\u onemax\u mp(tgt\u重量)
感谢您的快速结果。以下是我的结果:TypeError:无法使用抽象att实例化抽象