我有一个类Individual
,它由类change_val
的实例组成。可以使用函数import numpy as np
import multiprocessing as mp
class Population(object):
def __init__(self, pool_proc):
self.individuals = []
self.pool_proc = pool_proc
def add_individual(self, individual):
self.individuals.append(individual)
def change_individuals_loop(self):
# in a loop, it works fine
for indi in self.individuals:
indi.change_val()
def change_individuals_multi(self):
# this does -of course - not work as change_val is not known. How would it be done correctly?
self.pool_proc.apply_async(change_val, self.individuals)
def print_pop(self):
for indi in self.individuals:
print "value: {}, exponent: {}".format(indi.val, indi.exponent)
class Individual(object):
def __init__(self, some_val, exponent):
self.val = some_val
self.exponent = exponent
def change_val(self):
self.val = self.val ** self.exponent
if __name__ == '__main__':
# just for reproducibility purposes
np.random.seed(1)
my_pool = mp.Pool(processes=5)
my_pop = Population(my_pool)
for indi in range(1, 6):
my_pop.add_individual(Individual(indi, np.random.choice(5)))
print "initially:"
my_pop.print_pop()
my_pop.change_individuals_loop()
print "\nfirst iteration:"
my_pop.print_pop()
来更改个体的属性;在我的实际代码中,这种变化可能需要很长时间,处理时间可能会因人而异。一个人的变化独立于其他个体,因此我想使用多处理来加速更新所有个体的过程(与仅使用简单的for循环相比)。
这是我的玩具系统代码的骨架:
change_individuals_multi
我的问题是如何重写函数change_individuals_loop
,以便它为我提供与self.pool_proc.apply_async(change_val, self.individuals)
相同的输出。
问题在于行
change_val
当然 - 不起作用,因为函数apply_async
未知。我如何修改此行或代码结构以使其工作?如果有更适合这些目的的事情而不是 var oAjax = new XMLHttpRequest;
oAjax.open( 'get', '/path/to/my/app.js' );
oAjax.setRequestHeader( 'Pragma', 'no-cache' );
oAjax.send();
oAjax.onreadystatechange = function() {
if( oAjax.readyState === 4 ) {
self.location.reload();
}
}
,那么这方面的建议非常受欢迎。
答案 0 :(得分:1)
将它变成一个函数:
self.pool_proc.apply_async(lambda individual: individual.change_val(), self.individuals)
要获取值,您需要返回一些内容,然后处理返回值。有很多方法可以做到这一点,例如:
from multiprocessing import Pool
def workerfn((ndx, individual)):
individual.change_val()
return ndx, individual.val
...
pool = Pool(...)
for ndx, val in pool.imap_unordered(workerfn, enumerate(self.individuals)):
self.individuals[ndx].val = val
更新:为什么10万人的多重治疗速度较慢?
大多数尝试过多线程/处理的人都会遇到这种情况。原因很简单:开销。在单线程版本中,您执行函数调用+指数+赋值,而在多线程版本中,您可以执行在单线程版本中执行的所有操作+启动流程池+序列化100K个人+反序列化100K个人+进程间通信(个人)+序列化100K结果+反序列化相同+进程间通信(结果)+将结果分配给对象...我不会感到惊讶它的速度较慢;-)
为了使多个进程在常规多核设置上更快地运行(我不是在谈论100个核心),您需要大量的工作/数据,分成更大的块,然后分配给每个进程。例如。除以100 000 /核心数量并发送个人列表,而不是逐个发送。
当您将对象发送到另一个进程时,Python需要序列化和反序列化它们,因为另一个进程运行一个完全独立的Python解释器。与发送诸如元组/列表/等基本类型相比,这需要花费大量时间。尝试发送计算参数而不是单个对象。
最后,要完成的工作量需要花费更长的时间来进行进程间调用+返回。