Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/346.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.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 使用concurrent.futures每秒并行调用一个fn_Python_Concurrent.futures - Fatal编程技术网

Python 使用concurrent.futures每秒并行调用一个fn

Python 使用concurrent.futures每秒并行调用一个fn,python,concurrent.futures,Python,Concurrent.futures,我一直在努力掌握如何使用concurrent.futures每秒调用函数3次,而不必等待函数返回。我会在打完所有需要打的电话后收集结果 这就是我现在所处的位置,我很惊讶这个示例函数中的sleep()阻止了我的代码启动下一块3个函数调用。显然,我对这里的文档理解不够:) 这段代码导致打印3个块,每个块之间的睡眠时间为10秒。我如何更改这段代码以确保在调用下一批之前不等待函数返回 感谢首先,对于当前区块(字母表,3):的每次迭代,您将创建一个新的ProcessPoolExecutor实例和futur

我一直在努力掌握如何使用concurrent.futures每秒调用函数3次,而不必等待函数返回。我会在打完所有需要打的电话后收集结果

这就是我现在所处的位置,我很惊讶这个示例函数中的sleep()阻止了我的代码启动下一块3个函数调用。显然,我对这里的文档理解不够:)

这段代码导致打印3个块,每个块之间的睡眠时间为10秒。我如何更改这段代码以确保在调用下一批之前不等待函数返回


感谢

首先,对于当前区块(字母表,3):的每次迭代,您将创建一个新的
ProcessPoolExecutor
实例和
futures
字典实例,以取代上一个实例。因此,as_completed(futures)中result的最后一个循环
将只打印提交的最后一个区块的结果。其次,也是我认为您挂起的原因,您的块由
管理,ProcessPoolExecutor(max_workers=3)作为executor:
将不会终止,直到
executor
提交的任务完成,并且至少需要10秒。因此,当前块的
下一次迭代(字母表,3):
块的执行频率不会超过每10秒一次

还请注意,由于相同的原因,导致as_completed(futures):的块
需要在
中移动,ThreadPoolExecutor(max_workers=26)作为执行器:
块。也就是说,如果它放在后面,则在所有任务完成之前不会执行它,因此您将无法“在任务完成时”获得结果

您需要按如下所示进行一些重新安排(我还修改了
print\u something
,以返回除
None
以外的内容。如果您有足够的工作人员(26人)来运行提交的26项任务,那么现在应该不会出现挂起。我怀疑您的桌面(如果您在PC上运行此功能)有26个内核来支持26个并发执行的进程。但我注意到,
print_something
只打印一个短字符串,然后休眠10秒,这允许它将其处理器交给池中的另一个进程。因此,对于cpu密集型任务,通过指定
max_workers
值g几乎没有什么好处在本例中,它比您计算机上实际的物理处理器/内核的数量还要多,但当您的任务花费很少的时间执行实际的Python字节码时,更有效的方法是使用线程而不是进程,因为创建线程的成本远低于创建进程的成本。但是,线程当您运行的任务主要由Python字节代码组成时,它的性能非常差,因为由于全局解释器锁(GIL)的序列化,这些代码无法并发执行

供您研究的主题:全局解释器锁(GIL)和Python字节码执行

更新以使用线程:

因此,我们应该用26个或更多的轻量级线程来代替
ProcessPoolExecutor
concurrent.futures
模块的优点是不需要更改其他代码。但最重要的是更改块结构,并使用单个
执行器

from concurrent.futures import ThreadPoolExecutor, as_completed
import time

def print_something(thing):
    # NOT cpu-intensive, so threads should work well here
    print(thing)
    time.sleep(10)
    return thing # so there is a non-None result
    

# define a generator
def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]

def main():
    chunk_number = 0
    alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
    futures = {}
    with ThreadPoolExecutor(max_workers=26) as executor:
        for current_chunk in chunks(alphabet, 3):  # Restrict to calling the function 3 times per second
            futures.update({executor.submit(print_something, thing): thing for thing in current_chunk })
            chunk_number += 1
            print('chunk %s' % chunk_number)
            time.sleep(1)

        # needs to be within the executor block else it won't run until all futures are complete    
        for result in as_completed(futures):
            print(result.result())

if __name__ == '__main__':
    main()

你能提供一些输出吗?@Algebra8当然-我得到
chunk1abc
,然后是10秒的延迟,然后
chunk2def
等等。你希望得到它们,而不必排队等待结果的完成
?我不在乎什么时候收到结果-我在乎的是确保每一秒都有功能on被调用3次。print_something()中的sleep()调用只是为了看看如果函数需要很长时间才能响应会发生什么(模拟缓慢的网络连接等)。我不希望函数的执行时间减慢调用它的速度。谢谢。结果仍然不是我所期望的-我现在得到了以下结果
chunk 1 a b c chunk 2 chunk 3 chunk 4 chunk 5 chunk 6 chunk 7 chunk 8 chunk 9 p d e f g h
,结果之间存在延迟。有什么想法吗?你真的不清楚你想要完成什么。现在你总共有3个处理器在处理27个“任务”。必须有延迟。在更改之前,您创建了多个池,每个池包含3个进程,或者至少尝试创建。但我的桌面PC只有8个内核,因此我将获得的最大多处理级别为8,因此最终需要等待。通过将
ProcessPoolExecutor
替换为
ThreadPoo,将代码更改为使用线程lExecutor
并指定
max_workers=27
或更多。然后让它运行。您可以使用线程,因为您的任务是I/O绑定的(它们大多等待)。通过最新的更改,我现在得到了我所期望的结果。对于您的解决方案的第一个版本,我希望看到立即打印3个块(在看到延迟之前,ProcessPoolExplorer初始化时使用的3个工作进程各一个。我不确定为什么您的第一个解决方案没有出现这种情况。感谢您在这方面的帮助,我重新思考了这个问题,我相信我对导致原始问题的原因有了更好的解释。请参阅更新的答案。
from concurrent.futures import ThreadPoolExecutor, as_completed
import time

def print_something(thing):
    # NOT cpu-intensive, so threads should work well here
    print(thing)
    time.sleep(10)
    return thing # so there is a non-None result
    

# define a generator
def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]

def main():
    chunk_number = 0
    alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
    futures = {}
    with ThreadPoolExecutor(max_workers=26) as executor:
        for current_chunk in chunks(alphabet, 3):  # Restrict to calling the function 3 times per second
            futures.update({executor.submit(print_something, thing): thing for thing in current_chunk })
            chunk_number += 1
            print('chunk %s' % chunk_number)
            time.sleep(1)

        # needs to be within the executor block else it won't run until all futures are complete    
        for result in as_completed(futures):
            print(result.result())

if __name__ == '__main__':
    main()