Python:ValueError:没有足够的值来解包(预期3,得1)

时间:2018-03-06 09:58:55

标签: python multiprocessing python-multiprocessing

我对python中的多处理库有点新意。我在youtube上观看了几个讲座,并实现了多处理过程的基本实例。我的问题是,我希望通过利用所有8个可用内核来加速我的代码。几天前我就这方面提出了类似的问题,但无法得出合理的答案。我回去做了彻底的家庭作业,现在在了解了游泳池的基础知识(多处理中的其他东西)之后,我有点陷入困境。我在SO处提出了类似的问题,例如这一问题 - (Python multiprocessing pool map with multiple arguments)和(Python multiprocessing pool.map for multiple arguments)。我甚至实现了前者提到的解决方案。但是我的代码仍然抛出这个错误 -

File "minimal_example_so.py", line 84, in <module>
    X,u,t=pool.starmap(solver,[args])
ValueError: not enough values to unpack (expected 3, got 1)

我的代码看起来像这样 -

import time 
ti=time.time()
import matplotlib.pyplot as plt
from scipy.integrate import ode
import numpy as np
from numpy import sin,cos,tan,zeros,exp,tanh,dot,array
from matplotlib import rc
import itertools
from const_for_drdo_mod4 import *
plt.style.use('bmh')
import mpltex
from functools import reduce
from multiprocessing import Pool
import multiprocessing
linestyles=mpltex.linestyle_generator()

def zetta(x,spr,c): 
    num=len(x)*len(c)
    Mu=[[] for i in range(len(x))]
    for i in range(len(x)):
        Mu[i]=np.zeros(len(c))
    m=[]
    for i in range(len(x)):
        for j in range(len(c)):
            Mu[i][j]=exp(-.5*((x[i]-c[j])/spr)**2)

    b=list(itertools.product(*Mu))
    for i in range(len(b)):
        m.append(reduce(lambda x,y:x*y,b[i]))

    m=np.array(m)
    S=np.sum(m)
    return m/S

def f(t,Y,a,b,spr,tim,so,k,K,C):
    x1,x2=Y[0],Y[1]
    e=x1-2
    de=-2*x1+a*x2+b*sin(x1)
    s=de+2*e
    xx=[e,de]
    sold,ti=so,tim
    #import pdb;pdb.set_trace()
    theta=Y[2:2+len(C)**len(xx)]
    Z=zetta(xx,spr,C)
    u=dot(Z,theta)
    Z1=list(Z)
    dt=time.time()-ti
    ti=time.time()
    sodt=(s-sold)/dt
    x1dot=de
    x2dot=-x2*cos(x1)+cos(2*x1)*u
    xdot=[x1dot,x2dot]
    thetadot=[-20*number*(sodt+k*s+K*tanh(s))-20*.1*number2 for number,number2 in zip(Z1,theta)]
    sold=s
    ydot=xdot+thetadot
    return [ydot,u]

def solver(t0,y0,t1,dt,a,b,spr,tim,so,k,K,C):
    num=2
    x,t=[[] for i in range(2+len(C)**num)],[]
    u=[]
    r=ode(lambda t,y,a,b,spr,tim,so,k,K,C: f(t,y,a,b,spr,tim,so,k,K,C)[0]).set_integrator('dopri5',method='bdf')
    r.set_initial_value(y0,t0).set_f_params(a,b,spr,tim,so,k,K,C)
    while r.successful() and r.t<t1:
        r.integrate(r.t+dt)
        for i in range(2+len(C)**num):
            x[i].append(r.y[i])

        u.append(f(r.t,r.y,a,b,spr,tim,so,k,K,C)[1])
        t.append(r.t)
    return x,u,t

if __name__=='__main__':
    spr,C=1.5,[-3,-1.5,0,1.5,3]
    num=2
    k,K=2,5
    tim,so=0,0
    a,b=1,2
    y0,T=[0.1,0],100
    x1=[0 for i in range(len(C)**num)]
    x0=y0+x1
    args=(0,x0,T,1e-2,a,b,spr,tim,so,k,K,C)
    pool=multiprocessing.Pool(3)
    X,u,t=pool.starmap(solver,[args])
    #X,u,t=solver(0,x0,T,1e-2,a,b,spr,tim,so,k,K,C)
    nam=["x1","x2"]
    pool.close()
    pool.join()
    plt.figure(1)
    for i in range(len(X[0:2])): 
        plt.plot(t,X[i],label=nam[i])
        plt.legend(loc='upper right')
    plt.figure(2)
    for i in range(len(X[2:])):
        plt.plot(t,X[i])
    plt.figure(3)
    plt.plot(t,u)
    plt.show()

这里我想告诉我所有的参数都是普通数字或列表/数组,需要传递给求解器方法。我尝试了几种方法,使用map甚至starmap将我的参数传递给池,但所有这些都是徒劳的。请提前帮助,谢谢。 PS-我的代码在没有池的情况下工作得很好。

1 个答案:

答案 0 :(得分:0)

您只使用一个参数元组列表调用starmap。因此,返回值也是一个包含一个元素的列表 - 通过一次调用solver返回的元组。所以你有效地说

X, u, t = [(x1, u1, t1)]

这就是为什么你得到了你得到的例外:你不能将一个值(返回的元组)解包为三个变量。如果您想在此使用starmap,则需要执行以下操作:

 [(X,u,t)] = pool.starmap(solver,[args])

代替。但是对于一组参数而言,使用apply更有意义,因为它是为单个调用而设计的:

 X,u,t = pool.apply(solver, args)