Python 似乎multiprocessing.pool接受相同的参数两次
我正在使用Python 似乎multiprocessing.pool接受相同的参数两次,python,python-multiprocessing,Python,Python Multiprocessing,我正在使用multiprocessing.pool并行执行多重集成 在这个程序中,我通过生成dW3D阵列,为不同的噪声实现集成了一个运动方程。程序的第一部分只是定义参数和生成计算所需的数组 我在函数外部生成dW,因为我知道,否则我必须在每个进程中重新设定种子,以避免获得相同的随机序列 Euler(replica)函数是必须并行化的函数。这包括对数值积分的单个过程进行循环。argreplica是存储在“replicas”数组中的我的系统副本的编号,这是在pool.map中传递的参数 import
multiprocessing.pool
并行执行多重集成
在这个程序中,我通过生成dW
3D阵列,为不同的噪声实现集成了一个运动方程。程序的第一部分只是定义参数和生成计算所需的数组
我在函数外部生成dW
,因为我知道,否则我必须在每个进程中重新设定种子,以避免获得相同的随机序列
Euler(replica)
函数是必须并行化的函数。这包括对数值积分的单个过程进行循环。argreplica
是存储在“replicas”数组中的我的系统副本的编号,这是在pool.map
中传递的参数
import numpy as np
from multiprocessing import Pool
# parameters
N = 30 # number of sites
T = 1 # total time
dt = 0.1 # time step
l = 0 # initially localized state on site l
e = 0.0 # site energy
v = 1.0 # hopping coefficient
mu, sigma = 0, 1.0 # average and variance of the gaussian distribution
num_replicas = 8 # number of replicas of the system
processes=2 # number of processes
# identity vector which represents the diagonal of the Hamiltonian
E = np.ones(N) * e
# vector which represents the upper/lower diagonal terms of the Hopping Matrix and the Hamiltonian
V = np.ones(N-1) * v
# definition of the tight-binding Hamiltonian (tridiagonal)
H = np.diag(E) + np.diag(V, k=1) + np.diag(V, k=-1)
# corner elements of the Hamiltonian
H[0, -1] = v
H[-1, 0] = v
# time array
time_array = np.arange(0, T, dt)
# site array
site_array = np.arange(N)
# initial state
psi_0 = np.zeros((N), dtype=complex)
psi_0[l] = 1. + 0.j
#initialization of the state array
Psi = np.zeros((len(time_array), N), dtype=complex)
Psi[0,:] = psi_0
# replicas 1D array
replicas = np.arange(0, num_replicas)
# random 2D array
dW = np.random.normal(mu, 1.0, (len(time_array), num_replicas, N)) * np.sqrt(dt)
def Euler(replica):
psi_0 = np.zeros((N), dtype=complex)
psi_0[l] = 1. + 0.j
psi = psi_0
for i in np.arange(1, len(time_array)):
psi += -1.j * (H @ psi) * dt - 1.j * sigma * psi * dW[i,replica,:] - 0.5 * (sigma**2) * psi * dt
psi /= np.sqrt(psi @ np.conj(psi))
Psi[i,:] = psi
return Psi
pool = Pool(processes)
Psi = pool.map(Euler, replicas)
Psi = np.asarray(Psi)
Psi = np.swapaxes(Psi,0,1)
print(Psi)
根据经验,我发现如果num\u replicas>4个进程
如pool.map
函数所示,那么两个进程似乎采用相同的参数,就好像相同的计算重复了两次。相反,从'num_副本中,我认为您应该初始化Euler函数中的psi_0和“psi”。
我试图重现您的结果,事实上,我发现当num\u replicas>4*个进程
时,您从多个处理器获得相同的结果。但我认为这是因为Psi,在你的例子中,它是一个全局变量
按如下方式修改代码,它会为每个num_副本提供不同的结果(顺便问一下,为什么要使用site_阵列?它不在任何地方使用)
正如@Fabrizio所指出的,Psi
在Euler
的调用之间共享。这通常是一件坏事,也是为什么“全局可变状态”是个坏主意的另一个例子。事情很容易以意想不到的方式破裂
在这种情况下,它失败的原因很微妙,这是由于在酸洗它们并将它们返回到父/控制过程之前,每个过程中的方式造成的。您可以通过将map
的chunksize
参数设置为1
来看到这一点,从而使其立即返回结果,因此不会覆盖中间结果
这相当于以下最小工作示例:
from multiprocessing import Pool
arr = [None]
def mutate_global(i):
arr[0] = i
return arr
with Pool(2) as pool:
out = pool.map(mutate_global, range(10), chunksize=5)
print(out)
上次我运行此程序时,我得到:
[[4], [4], [4], [4], [4], [9], [9], [9], [9], [9]]
您可以更改chunksize
参数来了解它在做什么,也可以使用以下版本运行:
def mutate_local(i):
arr = [None]
arr[0] = i
return arr
它“只起作用”,等同于@Fabrizio所描述的在Euler
内部创建Phi
而不是使用单个全局变量
def mutate_local(i):
arr = [None]
arr[0] = i
return arr