在课堂上使用多处理模块

时间:2018-04-30 10:38:51

标签: python python-multiprocessing

我有以下程序,我想使用多处理模块。它使用外部文件,我在其中从另一个文件调用PSO类。 costfunc是来自另一个文件的函数,其他args只是变量。

Swarm是一个包含与ps的值一样多的对象的列表,每个对象都有多个属性,需要在每次迭代时更新。

在Hannu实现了multiprocessing.pool并且它正在工作,但是它比连续运行花费更多的时间。

如果您能告诉我它发生的原因是什么以及如何让它运行得更快,我将不胜感激?

# IMPORT PACKAGES -----------------------------------------------------------+
    import random
    import numpy as np
    # IMPORT FILES --------------------------------------------------------------+
    from Reducer import initial

    # Particle Class ------------------------------------------------------------+
    class Particle:
        def __init__(self,D,bounds_x,bounds_v):
            self.Position_i = []          # particle position
            self.Velocity_i = []          # particle velocity
            self.Cost_i = -1              # cost individual
            self.Position_Best_i = []     # best position individual
            self.Cost_Best_i = -1         # best cost individual
            self.Constraint_Best_i = []   # best cost individual contraints 
            self.Constraint_i = []        # constraints individual
            self.Penalty_i = -1           # constraints individual  

            x0,v0 = initial(D,bounds_x,bounds_v)

            for i in range(0,D):
                self.Velocity_i.append(v0[i])
                self.Position_i.append(x0[i])

        # evaluate current fitness
        def evaluate(self,costFunc,i):
            self.Cost_i, self.Constraint_i,self.Penalty_i = costFunc(self.Position_i,i)

            # check to see if the current position is an individual best
            if self.Cost_i < self.Cost_Best_i or self.Cost_Best_i == -1:
                self.Position_Best_i = self.Position_i
                self.Cost_Best_i = self.Cost_i
                self.Constraint_Best_i = self.Constraint_i
                self.Penalty_Best_i = self.Penalty_i

            return self

    def proxy(gg, costf, i):
        print(gg.evaluate(costf, i))


    # Swarm Class ---------------------------------------------------------------+
    class PSO():
        def __init__(self,costFunc,bounds_x,bounds_v,ps,D,maxiter):

            self.Cost_Best_g = -1       # Best Cost for Group
            self.Position_Best_g = []   # Best Position for Group
            self.Constraint_Best_g = []
            self.Penalty_Best_g = -1

            # Establish Swarm
            Swarm = []
            for i in range(0,ps):
                Swarm.append(Particle(D,bounds_x,bounds_v))

            # Begin optimization Loop
            i = 1
            self.Evol = []
            while i <= maxiter:
                pool = multiprocessing.Pool(processes = 4)
                results = pool.map_async(partial(proxy, costf = costFunc, i=i), Swarm)
                pool.close()
                pool.join()

                Swarm = results.get()

                if Swarm[j].Cost_i< self.Cost_Best_g or self.Cost_Best_g == -1:
                        self.Position_Best_g = list(Swarm[j].Position_i)
                        self.Cost_Best_g = float(Swarm[j].Cost_i)
                        self.Constraint_Best_g = list(Swarm[j].Constraint_i)
                        self.Penalty_Best_g = float(Swarm[j].Penalty_i)

                self.Evol.append(self.Cost_Best_g)
                i += 1

1 个答案:

答案 0 :(得分:1)

您需要一个代理函数来执行函数调用,并且当您需要为函数提供参数时,您还需要partial。考虑一下:

from time import sleep
from multiprocessing import Pool
from functools import partial

class Foo:
    def __init__(self, a):
        self.a = a
        self.b = None

    def evaluate(self, CostFunction, i):
        xyzzy = CostFunction(i)
        sleep(0.01)
        self.b = self.a*xyzzy
        return self

def CostFunc(i):
    return i*i

def proxy(gg, costf, i):
    return gg.evaluate(costf, i)

def main():
    Swarm = []
    for i in range(0,10):
        nc = Foo(i)
        Swarm.append(nc)

    p = Pool()
    for i in range(100,102):
        results = p.map_async(partial(proxy, costf=CostFunc, i=i), Swarm)
    p.close()
    p.join()

    Swarm = []
    for a in results.get():
        Swarm.append(a)

    for s in Swarm:
        print (s.b)

main()

这将创建一个Swarm对象列表,并且在每个对象中都有evaluate这是您需要调用的函数。然后我们有参数(CostFunc和代码中的整数)。

现在我们将使用Pool.map_async将您的Swarm列表映射到您的池中。这为每个工作人员提供了一个来自您的Swarm列表的Foo实例,我们有一个proxy函数实际调用evaluate()

但是,由于apply_async只将一个对象从iterable发送到函数,而不是使用proxy作为目标函数来汇集,我们使用partial来创建目标函数传递“固定”参数。

当你显然想要修改对象时,这需要另一个技巧。如果在池进程中修改目标对象,它只会修改本地副本,并在处理完成后立即将其抛出。无论如何,子进程都无法修改主进程内存(反之亦然),这会导致分段错误。

相反,在修改对象后,我们返回self。当您的池完成其工作后,我们会丢弃旧的Swarm并从结果对象中重新组合它。