Python根据可用RAM和函数参数的数量动态控制多处理脚本中的进程数

Python根据可用RAM和函数参数的数量动态控制多处理脚本中的进程数,python,multiprocessing,Python,Multiprocessing,对于python,我有一个不同寻常的问题。我正在使用多处理库映射函数f((dynamic1,dynamic2),fix1,fix2) 我希望动态控制活动进程的数量,因为函数实际上有时会泵送大量RAM。其思想是在每次迭代时(即在调用函数f之前)检查sum(dyn)是否低于阈值,以及RAM量是否高于阈值。如果条件匹配,则可以启动新进程并计算函数 另外一个条件是最大进程数:PC上的内核数 谢谢你的帮助:) 编辑:详细说明原因。 某些参数组合将具有高RAM消耗(在一个进程上高达80 Gb)。我或多或少地

对于python,我有一个不同寻常的问题。我正在使用
多处理
库映射函数
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)