Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.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';s multiprocessing.pool.map来处理相同的整数_Python_Asynchronous_Multiprocessing_Shared Memory_Shared State - Fatal编程技术网

使用Python';s multiprocessing.pool.map来处理相同的整数

使用Python';s multiprocessing.pool.map来处理相同的整数,python,asynchronous,multiprocessing,shared-memory,shared-state,Python,Asynchronous,Multiprocessing,Shared Memory,Shared State,问题 我使用Python的多处理模块异步执行函数。我想做的是能够在每个进程调用和执行def add_print时跟踪脚本的总体进度。例如,我希望下面的代码将1添加到total,并在每次进程运行该函数时打印出值(12318 19 20)。我的第一次尝试是使用全局变量,但没有成功。由于函数是异步调用的,因此每个进程从0开始读取total,并独立于其他进程添加1。因此,输出是201,而不是递增值 即使函数是异步运行的,我怎么能以同步方式从映射函数中引用相同的内存块呢?我的一个想法是以某种方式将tota

问题

我使用Python的多处理模块异步执行函数。我想做的是能够在每个进程调用和执行
def add_print
时跟踪脚本的总体进度。例如,我希望下面的代码将1添加到
total
,并在每次进程运行该函数时打印出值(
12318 19 20
)。我的第一次尝试是使用全局变量,但没有成功。由于函数是异步调用的,因此每个进程从0开始读取
total
,并独立于其他进程添加1。因此,输出是20
1
,而不是递增值

即使函数是异步运行的,我怎么能以同步方式从映射函数中引用相同的内存块呢?我的一个想法是以某种方式将
total
缓存在内存中,然后在添加到
total
时引用该内存块。在python中,这是一种可行且基本合理的方法吗

请让我知道,如果你需要更多的信息或如果我没有解释的东西不够好

谢谢


代码

#!/usr/bin/python

## Import builtins
from multiprocessing import Pool 

total = 0

def add_print(num):
    global total
    total += 1
    print total


if __name__ == "__main__":
    nums = range(20)

    pool = Pool(processes=20)
    pool.map(add_print, nums)
您可以使用:

池初始值设定项为每个辅助进程调用一次
setup
<代码>设置 使
total
成为工作进程中的全局变量,因此可以 当工作人员调用
add\u print
时,可在
add\u print
内访问


注意,进程数不应超过您的计算机拥有的CPU数。如果这样做,多余的子进程将等待CPU可用。因此,除非您有20个或更多CPU,否则不要使用
进程=20
。如果不提供
进程
参数,
多处理
将检测可用CPU的数量,并为您生成一个包含这么多工作线程的池。任务的数量(例如
nums
的长度)通常大大超过CPU的数量。那很好;当工作人员可用时,任务将由其中一个工作人员排队和处理。

执行类似操作(为进度设置全局变量等)会强制同步,因此可能会限制您的性能。如果您有足够大的工作单元并且很少更新变量,则不太可能。在一个紧密的循环中做这件事可能会让你跛脚。这正是我想要的。我想说的是,我在文档中遗漏了这一点,但我从未意识到该模块处理共享状态。另外,请注意处理器设置!有了这个答案,我再高兴不过了!在仔细考虑了一下您的答案之后,我注意到设置
processes=8
processes=20
在行为上有明显的不同。根据您的解释,听起来这两种设置应该导致相同的操作。不是这样吗?顺便说一下,我有8个CPU。如果你使用的是Windows,我应该提到这将在OSX和Ubuntu上使用。你不会很容易面临竞争条件吗?
import multiprocessing as mp

def add_print(num):
    """
    https://eli.thegreenplace.net/2012/01/04/shared-counter-with-pythons-multiprocessing
    """
    with lock:
        total.value += 1
    print(total.value)

def setup(t, l):
    global total, lock
    total = t
    lock = l

if __name__ == "__main__":
    total = mp.Value('i', 0)
    lock = mp.Lock()
    nums = range(20)
    pool = mp.Pool(initializer=setup, initargs=[total, lock])
    pool.map(add_print, nums)