Python根据可用RAM和函数参数的数量动态控制多处理脚本中的进程数
对于python,我有一个不同寻常的问题。我正在使用Python根据可用RAM和函数参数的数量动态控制多处理脚本中的进程数,python,multiprocessing,Python,Multiprocessing,对于python,我有一个不同寻常的问题。我正在使用多处理库映射函数f((dynamic1,dynamic2),fix1,fix2) 我希望动态控制活动进程的数量,因为函数实际上有时会泵送大量RAM。其思想是在每次迭代时(即在调用函数f之前)检查sum(dyn)是否低于阈值,以及RAM量是否高于阈值。如果条件匹配,则可以启动新进程并计算函数 另外一个条件是最大进程数:PC上的内核数 谢谢你的帮助:) 编辑:详细说明原因。 某些参数组合将具有高RAM消耗(在一个进程上高达80 Gb)。我或多或少地
多处理
库映射函数f((dynamic1,dynamic2),fix1,fix2)
我希望动态控制活动进程的数量,因为函数实际上有时会泵送大量RAM。其思想是在每次迭代时(即在调用函数f
之前)检查sum(dyn)
是否低于阈值,以及RAM量是否高于阈值。如果条件匹配,则可以启动新进程并计算函数
另外一个条件是最大进程数:PC上的内核数
谢谢你的帮助:)
编辑:详细说明原因。
某些参数组合将具有高RAM消耗(在一个进程上高达80 Gb)。我或多或少地知道哪些进程将使用大量RAM,当程序遇到它们时,我希望等待另一个进程结束,在单个进程中启动这个高RAM消耗组合,然后在组合的其余部分使用更多进程继续计算以映射
根据以下答案编辑我的尝试:
它不起作用,但不会引起错误。它只是完成了程序
# Imports
import itertools
import concurrent.futures
# Parameters
N = int(input("Number of CPUs to use: "))
t0 = 0
tf = 200
s_step = 0.05
max_s = None
folder = "test"
possible_dynamics = [My_class(x) for x in [20, 30, 40, 50, 60]]
dynamics_to_compute = [list(x) for x in itertools.combinations_with_replacement(possible_dynamics , 2)] + [list(x) for x in itertools.combinations_with_replacement(possible_dynamics , 3)]
function_inputs = [(dyn , t0, tf, s_step, max_s, folder) for dyn in dynamics_to_compute]
# -----------
# Computation
# -----------
start = time.time()
# Pool creation and computation
futures = []
pool = concurrent.futures.ProcessPoolExecutor(max_workers = N)
for Obj, t0, tf, s_step, max_s, folder in function_inputs:
if large_memory(Obj, s_step, max_s):
concurrent.futures.wait(futures) # wait for all pending tasks
large_future = pool.submit(compute, Obj, t0, tf,
s_step, max_s, folder)
large_future.result() # wait for large computation to finish
else:
future = pool.submit(compute, Obj, t0, tf,
s_step, max_s, folder)
futures.append(future)
end = time.time()
if round(end-start, 3) < 60:
print ("Complete - Elapsed time: {} s".format(round(end-start,3)))
else:
print ("Complete - Elapsed time: {} mn and {} s".format(int((end-start)//60), round((end-start)%60,3)))
os.system("pause")
#导入
进口itertools
进口期货
#参数
N=int(输入(“要使用的CPU数量:”)
t0=0
tf=200
s_阶跃=0.05
最大值=无
folder=“测试”
可能的_动态=[20,30,40,50,60]中x的我的_类(x)]
动力学计算=[itertools中x的列表(x).带替换的组合(可能的动态,2)]+[itertools中x的列表(x).带替换的组合(可能的动态,3)]
函数输入=[(dyn,t0,tf,s_步长,max_s,文件夹)用于动态计算中的dyn
# -----------
#计算
# -----------
开始=时间。时间()
#池的创建和计算
期货=[]
pool=concurrent.futures.ProcessPoolExecutor(最大值=N)
对于Obj、t0、tf、s_步骤、最大值、功能输入中的文件夹:
如果内存较大(Obj、s\U步长、最大值):
concurrent.futures.wait(futures)#等待所有挂起的任务
大型未来=池。提交(计算、Obj、t0、tf、,
s_步骤,最大值,文件夹)
大型_future.result()#等待大型计算完成
其他:
future=pool.submit(compute、Obj、t0、tf、,
s_步骤,最大值,文件夹)
futures.append(未来)
end=time.time()
如果圆形(结束-开始,3)<60:
打印(“完成-运行时间:{}s”。格式(四舍五入(结束-开始,3)))
其他:
打印(“完成-经过的时间:{}mn和{}s”。格式(int((结束-开始)//60),四舍五入((结束-开始)%60,3)))
操作系统(“暂停”)
这仍然是我代码的一个简化示例,但其思想就在这里。它的运行时间不到0.2秒,这意味着他实际上从未调用过函数compute
注意:
Obj
不是实际的变量名。要实现这一点,您需要放弃使用map
来获得对任务执行流程的更多控制
这段代码实现了您在问题末尾描述的算法。我建议使用concurrent.futures
库,因为它公开了一组更整洁的API
import concurrent.futures
pool = concurrent.futures.ProcessPoolExecutor(max_workers=6)
futures = []
for dyn, fix1, fix2 in dynamic_duos:
if large_memory(dyn, fix1, fix2):
concurrent.futures.wait(futures) # wait for all pending tasks
large_future = pool.submit(f, dyn, fix1, fix2)
large_future.result() # wait for large computation to finish
else:
future = pool.submit(f, dyn, fix1, fix2)
futures.append(future)
谢谢你的回复。我不介意去掉
map
,但是我只想快速澄清一下futures
列表。未来究竟是什么?。我的函数实际上不返回任何内容,而是在目录中创建pickle文件(直接在函数的末尾实现)。如果我正确获取了上面的代码,pool.submit()
将要求工作池处理一个输入。但我不太明白futures list在这里做什么。A是表示函数异步执行的处理程序。它是一种任务
对象,您可以使用它来检索计算结果或只是等待其结论。futures
列表允许您在执行大任务之前等待所有其他正在运行的任务完成(通过wait
函数)。需要明确的是:每次启动小内存任务时,它都会附加到列表futures
。附加的是处理程序,因此concurrent.futures.wait(futures)
等待futures
中所有尚未完成的处理程序完成其任务。对的因此,最后,列表futures
将每个小内存任务都表示为一个处理程序?而行large\u future.result()
将等待刚刚开始的大型循环结束,然后再转到for
循环的下一次迭代。如果这是正确的,那么我就明白了:)另外一个问题:在一台有8个物理核和16个逻辑核的PC上,我猜想在多处理中,逻辑核的使用率很低,因为操作系统是如何安排CPU使用的。i、 e.有了这个代码,max_workers
应该是8对吗?上一个问题是,我无法让它运行。从未调用函数f
。有关代码的详细信息,请参见编辑。。。谢谢你的帮助:)
import concurrent.futures
pool = concurrent.futures.ProcessPoolExecutor(max_workers=6)
futures = []
for dyn, fix1, fix2 in dynamic_duos:
if large_memory(dyn, fix1, fix2):
concurrent.futures.wait(futures) # wait for all pending tasks
large_future = pool.submit(f, dyn, fix1, fix2)
large_future.result() # wait for large computation to finish
else:
future = pool.submit(f, dyn, fix1, fix2)
futures.append(future)