Python 多处理卡住了
Python multiprocessing gets stuck
我是 Python 的新手,也是多处理的新手,我在网上找到了一些教程来帮助我理解多处理包。
我的代码有一组使用 RungeKutta4 方法的微分方程,我需要 运行 大量具有不同起始条件的计算。
代码本身可以工作,但没有多处理需要很长时间才能完成,我认为使用并行化可能是理想的,因为计算是独立的....
我正在使用 Anaconda 作为 IDE 顺便说一句..
所以我用了
import multiprocessing as mp
iterations = np.arange(start,end,step)
pool = mp.Pool(mp.cpu_count()) # Step 1: Init multiprocessing.Pool()
results = pool.map(rungeKutta4, [k for k in iterations]) # Step 2: apply pool map
pool.close() # Step 3: close
当我在 Anaconda 中 运行 它时,我没有收到错误,它开始计算但从未停止....
我哪里错了?
在此先感谢您的帮助...
最佳
编辑:我在此处添加了整个代码...
# Python program to implement Runge Kutta method
# Markus Schmid
# 2020 Appalachian State University
# jupyter nbconvert --to python FILENAME.ipynb
# y" + 2*beta*y' + w0*sin(y) = A + B*cos(w*t)
# Import used libraries
import numpy as np
import math
import matplotlib.pyplot as plt
import time
from matplotlib import rc
rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
rc('text', usetex=True)
import multiprocessing as mp
print("Number of processors: ", mp.cpu_count())
# list for time (x axis) and result (y axis)
result = []
w0 = 10 # undamped angular frequency of the oscillator
beta = 1
B = 1
A = 0
B = 10
w = 4
theta_init = 0
theta_end = 20
theta_step = 0.1
# initial conditions
t0 = 0
y0 = 0
z0 = 0
t_final = 20 # final time
h = 0.01 # fixed step size
n = (int)((t_final - t0)/h) # datapoints per RK4 iteration
# define functions
def funcf(t, y, z):
return (z)
def funcg(t, y, z):
return (A+B*math.cos(w*t) - 2*beta*z - w0*math.sin(y))
# Finds value of y for a given x using step size h
# and initial value y0 at x0.
def rungeKutta4(y):
# Count number of iterations using step size or
# step height h
t = t0
z = z0
n = (int)((t_final - t)/h)
for i in range(1, n + 1):
# Apply Runge Kutta to find next value of y
k1 = h * funcf(t, y, z)
l1 = h * funcg(t, y, z)
k2 = h * funcf(t + 0.5 * h, y + 0.5 * k1, z + 0.5 * l1)
l2 = h * funcg(t + 0.5 * h, y + 0.5 * k1, z + 0.5 * l1)
k3 = h * funcf(t + 0.5 * h, y + 0.5 * k2, z + 0.5 * l2)
l3 = h * funcg(t + 0.5 * h, y + 0.5 * k2, z + 0.5 * l2)
k4 = h * funcf(t + h, y + k3, z + l3)
l4 = h * funcg(t + h, y + k3, z + l3)
# Update next value of y
y = y + (1.0 / 6.0)*(k1 + 2 * k2 + 2 * k3 + k4)
z = z + (1.0 / 6.0)*(l1 + 2 * l2 + 2 * l3 + l4)
#result.append(y)
t = t + h # Update next value of t
return y
iterations = np.arange(theta_init,theta_end+theta_step,theta_step) # number iterations for omega sweep
start_time = time.time()
#for k in iterations: # for serial calculation
# rungeKutta4(k)
pool = mp.Pool(mp.cpu_count()) # Step 1: Init multiprocessing.Pool()
results = pool.map(rungeKutta4, [k for k in iterations]) # Step 2: apply pool map
end_time = time.time()
pool.close() # Step 3: close
print ("The program took", end_time - start_time, "s to run")
#table = np.array(result).reshape(len(iterations),n) # rearrange array, 1 row is const. theta0
timer = np.arange(t0,t_final,h) # time array
你的代码看起来不错,对我有用(Ipython 和 python3.6.9),我在下面附上了结果和配置。
您是否尝试在另一个 python virtual environment(Anaconda 之外)中 运行 它?
正如之前所说(在罗纳德的评论中)other IDE's have bugs with python's multiprocessing, try run it using the command line/Ipython. I have previously encountered one even in vscode
配置:
结果:
我的初始评论:
IDE's can interact with Python in unexpected ways. There are several mentions of multiprocessing misbehaving in IDE's on Whosebug. Therefore it is probably best to test your script by directly calling Python from a shell (cmd.exe on ms-windows).
您回复了:
RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase.
为了 multiprocessing
在 ms-windows 上正常运行,您必须能够在脚本中导入代码 并且没有副作用,例如启动新进程.
这意味着您必须将除导入和 function/class 定义之外的所有内容都放在主块中,例如受文档启发的示例:
from multiprocessing import Process
def foo():
print('hello')
if __name__ == '__main__':
p = Process(target=foo)
p.start()
基本上,ms-windows 缺少类 UNIX 系统上存在的漂亮的 fork()
系统调用。
所以 Python 开发人员不得不想出一个聪明的 hack 来让 multiprocessing
在 ms-windows 上工作。
参见例如this answer 血淋淋的细节。
Edit ms-windows上好像也需要把worker函数放到自己的文件里导入。参见例如here.
我找到了在 Anaconda 中运行的解决方案。
除了
if __name__ == '__main__':
被调用的函数(worker)必须在它自己的 .py 文件中,必须在开头导入..
我把 RK4 放在一个 RK4.py 文件中,我在开始时导入了它,但它不起作用,但在我的情况下,来回传递值会带来新问题...
我是 Python 的新手,也是多处理的新手,我在网上找到了一些教程来帮助我理解多处理包。
我的代码有一组使用 RungeKutta4 方法的微分方程,我需要 运行 大量具有不同起始条件的计算。
代码本身可以工作,但没有多处理需要很长时间才能完成,我认为使用并行化可能是理想的,因为计算是独立的....
我正在使用 Anaconda 作为 IDE 顺便说一句..
所以我用了
import multiprocessing as mp
iterations = np.arange(start,end,step)
pool = mp.Pool(mp.cpu_count()) # Step 1: Init multiprocessing.Pool()
results = pool.map(rungeKutta4, [k for k in iterations]) # Step 2: apply pool map
pool.close() # Step 3: close
当我在 Anaconda 中 运行 它时,我没有收到错误,它开始计算但从未停止.... 我哪里错了?
在此先感谢您的帮助...
最佳
编辑:我在此处添加了整个代码...
# Python program to implement Runge Kutta method
# Markus Schmid
# 2020 Appalachian State University
# jupyter nbconvert --to python FILENAME.ipynb
# y" + 2*beta*y' + w0*sin(y) = A + B*cos(w*t)
# Import used libraries
import numpy as np
import math
import matplotlib.pyplot as plt
import time
from matplotlib import rc
rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
rc('text', usetex=True)
import multiprocessing as mp
print("Number of processors: ", mp.cpu_count())
# list for time (x axis) and result (y axis)
result = []
w0 = 10 # undamped angular frequency of the oscillator
beta = 1
B = 1
A = 0
B = 10
w = 4
theta_init = 0
theta_end = 20
theta_step = 0.1
# initial conditions
t0 = 0
y0 = 0
z0 = 0
t_final = 20 # final time
h = 0.01 # fixed step size
n = (int)((t_final - t0)/h) # datapoints per RK4 iteration
# define functions
def funcf(t, y, z):
return (z)
def funcg(t, y, z):
return (A+B*math.cos(w*t) - 2*beta*z - w0*math.sin(y))
# Finds value of y for a given x using step size h
# and initial value y0 at x0.
def rungeKutta4(y):
# Count number of iterations using step size or
# step height h
t = t0
z = z0
n = (int)((t_final - t)/h)
for i in range(1, n + 1):
# Apply Runge Kutta to find next value of y
k1 = h * funcf(t, y, z)
l1 = h * funcg(t, y, z)
k2 = h * funcf(t + 0.5 * h, y + 0.5 * k1, z + 0.5 * l1)
l2 = h * funcg(t + 0.5 * h, y + 0.5 * k1, z + 0.5 * l1)
k3 = h * funcf(t + 0.5 * h, y + 0.5 * k2, z + 0.5 * l2)
l3 = h * funcg(t + 0.5 * h, y + 0.5 * k2, z + 0.5 * l2)
k4 = h * funcf(t + h, y + k3, z + l3)
l4 = h * funcg(t + h, y + k3, z + l3)
# Update next value of y
y = y + (1.0 / 6.0)*(k1 + 2 * k2 + 2 * k3 + k4)
z = z + (1.0 / 6.0)*(l1 + 2 * l2 + 2 * l3 + l4)
#result.append(y)
t = t + h # Update next value of t
return y
iterations = np.arange(theta_init,theta_end+theta_step,theta_step) # number iterations for omega sweep
start_time = time.time()
#for k in iterations: # for serial calculation
# rungeKutta4(k)
pool = mp.Pool(mp.cpu_count()) # Step 1: Init multiprocessing.Pool()
results = pool.map(rungeKutta4, [k for k in iterations]) # Step 2: apply pool map
end_time = time.time()
pool.close() # Step 3: close
print ("The program took", end_time - start_time, "s to run")
#table = np.array(result).reshape(len(iterations),n) # rearrange array, 1 row is const. theta0
timer = np.arange(t0,t_final,h) # time array
你的代码看起来不错,对我有用(Ipython 和 python3.6.9),我在下面附上了结果和配置。
您是否尝试在另一个 python virtual environment(Anaconda 之外)中 运行 它? 正如之前所说(在罗纳德的评论中)other IDE's have bugs with python's multiprocessing, try run it using the command line/Ipython. I have previously encountered one even in vscode
配置:
结果:
我的初始评论:
IDE's can interact with Python in unexpected ways. There are several mentions of multiprocessing misbehaving in IDE's on Whosebug. Therefore it is probably best to test your script by directly calling Python from a shell (cmd.exe on ms-windows).
您回复了:
RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase.
为了 multiprocessing
在 ms-windows 上正常运行,您必须能够在脚本中导入代码 并且没有副作用,例如启动新进程.
这意味着您必须将除导入和 function/class 定义之外的所有内容都放在主块中,例如受文档启发的示例:
from multiprocessing import Process
def foo():
print('hello')
if __name__ == '__main__':
p = Process(target=foo)
p.start()
基本上,ms-windows 缺少类 UNIX 系统上存在的漂亮的 fork()
系统调用。
所以 Python 开发人员不得不想出一个聪明的 hack 来让 multiprocessing
在 ms-windows 上工作。
参见例如this answer 血淋淋的细节。
Edit ms-windows上好像也需要把worker函数放到自己的文件里导入。参见例如here.
我找到了在 Anaconda 中运行的解决方案。
除了
if __name__ == '__main__':
被调用的函数(worker)必须在它自己的 .py 文件中,必须在开头导入..
我把 RK4 放在一个 RK4.py 文件中,我在开始时导入了它,但它不起作用,但在我的情况下,来回传递值会带来新问题...