Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用多处理时,是否设置池映射操作的时间限制?_Python_Multiprocessing - Fatal编程技术网

Python 使用多处理时,是否设置池映射操作的时间限制?

Python 使用多处理时,是否设置池映射操作的时间限制?,python,multiprocessing,Python,Multiprocessing,在Python中使用多处理时,是否可以对pool map()操作设置时间限制。当达到时间限制时,所有子进程将停止并返回它们已有的结果 import multiprocessing as mp def task(v): do something return result if __name__ == '__main__': vs = [...] p= mp.Pool() results = p.map(task, vs) 在上面的例子中,我有一个非常

在Python中使用
多处理
时,是否可以对
pool map()
操作设置时间限制。当达到时间限制时,所有子进程将停止并返回它们已有的结果

import multiprocessing as mp

def task(v):
    do something
    return result

if __name__ == '__main__':
    vs = [...]
    p= mp.Pool()
    results = p.map(task, vs)
在上面的例子中,我有一个非常大的列表
vs
。理想情况下,列表
vs
中的所有元素都将被发送到函数
task()
,所有结果都将保存在
results
列表中

然而,由于列表
vs
非常大,我只有有限的时间来执行这个过程(比如5分钟)。我需要的是在达到5分钟时停止
map
过程,并将计算结果返回到列表
results

EDIT1:

我不会放弃一项需要5分钟以上才能完成的任务。假设列表中有1000个任务,5分钟后只完成600个任务。我需要的是杀死所有的子进程,并将这600个任务的结果保存到
结果
列表中。

我看过,它使用了一种叫做
Pebble
的东西。首先,我不理解关于“Python标准池不支持超时”的评论。它的方式是,您可以等待指定的时间量以返回结果,并通过异常通知它是否存在超时,或者您可以对指定超时的结果对象发出等待。在这种情况下不会返回异常,但您可以测试处理结果的“作业”是否已完成。但是,您确实不能终止单个超时作业。但是,当处理完所有未超时的结果后,可以对池本身调用
terminate
,这将终止池中的所有进程,无论它们是否空闲。这导致了回答中的第二条评论,“突然终止进程可能会导致应用程序中出现奇怪的行为。”这取决于超时的作业所做的工作。因此,我们同意,如果这样做可能导致奇怪的行为,我们不应该过早地暂停工作和终止工作。但我看不出
Pebble
如何更好地处理这个问题

这个问题的答案是答案,实际上有一种技巧可以让你做你想做的事情。您需要放弃使用
map
函数,转而使用
apply\u async
指定回调函数,以便在结果可用时保存结果。在下面的示例中,我使用5秒的超时值只是为了演示,并且已经安排了我提交给超时的10个作业中的大约一半。我已经预先分配了一个名为
squares
的结果列表,该列表将保存10个结果,并且已经用10个
None
值初始化。当我们都完成时,如果第i个值是
None
,那是因为处理值
i
的作业超时了。My workder函数还返回其参数
v
,以及其计算值
v**2
,以便回调函数知道计算结果应位于
正方形列表中的哪个位置:

import multiprocessing as mp
import time

def my_task(v):
    time.sleep(v)
    return v, v ** 2

squares = [None] * 10

def my_callback(t):
    i, s = t
    squares[i] = s


TIMEOUT = 5

if __name__ == '__main__':
    vs = range(10)
    pool = mp.Pool()
    results = [pool.apply_async(my_task, args=(v,), callback=my_callback) for v in vs]
    time.sleep(TIMEOUT)
    pool.terminate() # all processes, busy or idle, will be terminated
    print(squares)
印刷品:

[0, 1, 4, 9, 16, None, None, None, None, None]
Timeout for v =  0
Return value for v = 1 is 1
Return value for v = 2 is 4
Return value for v = 3 is 9
Return value for v = 4 is 16
Timeout for v =  5
Timeout for v =  6
第二个更复杂的方法不使用回调函数。而是对调用
池返回的每个
AsynchResult
实例执行
get
调用。apply\u async
指定超时值。这里需要技巧的是,对于初始调用,您必须使用完整的超时值。但当结果返回或出现超时异常时,您已经等待了一段时间,
t
。这意味着您下次获得超时结果时,您指定的超时值应减少
t

import multiprocessing as mp
import time

def my_task(v):
    time.sleep(6 if v == 0 else v)
    return v ** 2


TIMEOUT = 5

if __name__ == '__main__':
    vs = range(mp.cpu_count() - 1) # 7 on my desktop
    pool = mp.Pool() # poolsize is 8
    results = [pool.apply_async(my_task, args=(v,)) for v in vs]
    time_to_wait = TIMEOUT # initial time to wait
    start_time = time.time()
    for i, result in enumerate(results):
        try:
            return_value = result.get(time_to_wait) # wait for up to time_to_wait seconds
        except mp.TimeoutError:
            print('Timeout for v = ', i)
        else:
            print(f'Return value for v = {i} is {return_value}')
        # how much time has exprired since we began waiting?
        t = time.time() - start_time
        time_to_wait = TIMEOUT - t
        if time_to_wait < 0:
            time_to_wait = 0
    pool.terminate() # all processes, busy or idle, will be terminated
注意


通过使用
apply\u async
而不是
map
,作业将以1的chunksize有效提交(请参阅
chunksize
map
参数,该参数确定iterable参数如何分解为“chunks”放在每个进程的输入队列上,以最大限度地减少共享内存传输的数量。对于大型iterables,
apply\u async
可能比
map
效率低,后者使用“合理的”默认的chunksize基于您的池大小和要处理的作业数。

这看起来很相似:是什么让您认为重新发布已结束问题的确切副本会给您带来不同的结果。[对于超过10K:@PM77-1,我编辑了已关闭的帖子,但我注意到它仍处于关闭状态,其他人可能看不到它,所以我重新发布here@ForceBru我会检查的。感谢这两种方法对我都有效。我对第二种方法有顾虑。在函数“我的任务”(v)中,我使用时间。睡眠(6)如果v==0,其他变量保持不变。在这种情况下,v为1-4的任务可以完成。在结果检索步骤中,它被设计成有序地检索结果。因此,v==0将消耗所有的等待时间,让其他变量等待的时间为0。虽然在我的笔记本电脑上,v=1到4的结果可以在等待时间为0的情况下成功检索,但我是同事当我们从等待时间为0的已完成任务中获得结果时,尤其是当硬件陈旧且速度缓慢时,它是否总是有效。如果您有
if v==0:time.sleep(6)
但没有其他作业休眠,则如果提交的作业数为,但作业数大于池大小,则第一个进程队列中至少有一个作业在第一个作业完成之前不会计划运行。因此,这些作业也将超时。这两种方法都适用。我已更新了第二个编码示例:当
v
为0时,让
my_task
睡眠6秒,否则它将像以前一样睡眠
v