使用 Python 的 multiprocessing.pool.map 来操作相同的整数
Using Python's multiprocessing.pool.map to manipulate the same integer
问题
我正在使用 Python 的多处理模块来异步执行函数。我想要做的是能够在每个进程调用和执行 def add_print
时跟踪我的脚本的总体进度。例如,我希望下面的代码在 total
上加 1 并在每次进程 运行 执行该功能时打印出值 (1 2 3 ... 18 19 20
)。我的第一次尝试是使用全局变量,但这没有用。由于该函数是异步调用的,因此每个进程读取 total
作为 0 开始,并独立于其他进程加 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)
您可以使用 shared Value
:
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)
池初始化程序为每个工作子进程调用一次 setup
。 setup
使 total
成为工作进程中的全局变量,因此 total
可以
当工作人员调用 add_print
.
时在 add_print
内部访问
请注意,进程数不应超过您机器的 CPU 数。如果这样做,多余的子进程将等待 CPU 可用。所以不要使用 processes=20
除非你有 20 个或更多的 CPU。如果您不提供 processes
参数,multiprocessing
将检测可用的 CPU 数量并为您生成一个包含那么多 worker 的池。任务的数量(例如 nums
的长度)通常大大超过 CPU 的数量。没关系;当工作人员可用时,任务由其中一名工作人员排队和处理。
问题
我正在使用 Python 的多处理模块来异步执行函数。我想要做的是能够在每个进程调用和执行 def add_print
时跟踪我的脚本的总体进度。例如,我希望下面的代码在 total
上加 1 并在每次进程 运行 执行该功能时打印出值 (1 2 3 ... 18 19 20
)。我的第一次尝试是使用全局变量,但这没有用。由于该函数是异步调用的,因此每个进程读取 total
作为 0 开始,并独立于其他进程加 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)
您可以使用 shared Value
:
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)
池初始化程序为每个工作子进程调用一次 setup
。 setup
使 total
成为工作进程中的全局变量,因此 total
可以
当工作人员调用 add_print
.
add_print
内部访问
请注意,进程数不应超过您机器的 CPU 数。如果这样做,多余的子进程将等待 CPU 可用。所以不要使用 processes=20
除非你有 20 个或更多的 CPU。如果您不提供 processes
参数,multiprocessing
将检测可用的 CPU 数量并为您生成一个包含那么多 worker 的池。任务的数量(例如 nums
的长度)通常大大超过 CPU 的数量。没关系;当工作人员可用时,任务由其中一名工作人员排队和处理。