多处理:不能在文件之间共享变量
Multiprocessing: cannot share a variable between files
我用一个最小的例子来描述我的问题。在我的项目中,一个 config
文件包含一个变量 param
,它被所有其他模块使用:
# config.py
param = -1
config
在 solver
中导入,它根据传递的 val
和来自配置的 param
执行计算:
# solver.py
import config
def solve(val):
# some computation using val and config.param
print('solver uses param:', config.param)
return None
我的目标是对一些 param
和各种 val
执行计算。
# main.py
import multiprocessing as mp
import config, solver
val_list = [None for i in range(3)]
pool = mp.Pool(10)
config.param = 1
print('testing param: ', config.param)
results = pool.map(solver.solve, [val for val in val_list]) # multiprocessing
#results = [solver.solve(val) for val in val_list] # basic
在使用多处理时我得到一个输出:
testing param: 1
solver uses param: -1
solver uses param: -1
solver uses param: -1
这意味着 param
在 main
中的变化不会被 solver
看到。但是,在使用基本的 for 循环计算时可以看到:
testing param: 1
solver uses param: 1
solver uses param: 1
solver uses param: 1
如何通过多处理获得所需的行为?请注意,param
的更改不应在 config
中手动完成,因为实际上我在 for 循环中测试了 param
的不同值。我在 Linux 上使用 Python 3.6.9。谢谢!
你调用 mp.Pool(10)
的那一刻你创建了 10 个处于“等待模式”的新进程,直到你给它们一些东西 运行,但是它们已经从你的进程中分叉出来所以任何改变局部变量不会影响它们
如果您想向他们传递信息,您需要:
在您调用它们时将其传递给它们(只需添加类似 pool.map(solver.solve, [(val, config.param) for val in val_list]
的内容,然后让 solve
拆分这些参数)
或者您需要使 config.param
成为一个可以在进程之间共享的变量,可能使用 multiprocessing.Value
像这样:
# config.py
import multiprocessing as mp
param = mp.Value("i", -1)
然后您可以像这样访问值:config.param.value
您可以覆盖 config.param 值,然后 mp.Pool()
启动如下。
# main.py
import multiprocessing as mp
import config, solver
config.param = 1 # trick is that
val_list = [None for i in range(3)]
pool = mp.Pool(10)
print('testing param: ', config.param)
results = pool.map(solver.solve, [val for val in val_list]) # multiprocessing
#results = [solver.solve(val) for val in val_list] # basic
我们需要 getter 和 setter 方法在 solver.py
中来保证 param
值的一致性。
#solver.py
import config
class Solver:
def __init__(self):
self._config = config.param
@property
def config(self):
return self._config
@config.setter
def config(self, cfgval):
self._config = cfgval
def solve(self, val):
# some computation using val and config.param
print('solver uses param:', self.config)
return None
然后您可以按照 main.py
.
中的预期对某些 param
和各种 val
执行计算
# main.py
import multiprocessing as mp
from solver import Solver
if __name__ == '__main__':
val_list = [None for i in range(3)]
pool = mp.Pool(10)
solver = Solver()
solver.config = 1
results = pool.map(solver.solve, [val for val in val_list]) # multiprocessing
我用一个最小的例子来描述我的问题。在我的项目中,一个 config
文件包含一个变量 param
,它被所有其他模块使用:
# config.py
param = -1
config
在 solver
中导入,它根据传递的 val
和来自配置的 param
执行计算:
# solver.py
import config
def solve(val):
# some computation using val and config.param
print('solver uses param:', config.param)
return None
我的目标是对一些 param
和各种 val
执行计算。
# main.py
import multiprocessing as mp
import config, solver
val_list = [None for i in range(3)]
pool = mp.Pool(10)
config.param = 1
print('testing param: ', config.param)
results = pool.map(solver.solve, [val for val in val_list]) # multiprocessing
#results = [solver.solve(val) for val in val_list] # basic
在使用多处理时我得到一个输出:
testing param: 1
solver uses param: -1
solver uses param: -1
solver uses param: -1
这意味着 param
在 main
中的变化不会被 solver
看到。但是,在使用基本的 for 循环计算时可以看到:
testing param: 1
solver uses param: 1
solver uses param: 1
solver uses param: 1
如何通过多处理获得所需的行为?请注意,param
的更改不应在 config
中手动完成,因为实际上我在 for 循环中测试了 param
的不同值。我在 Linux 上使用 Python 3.6.9。谢谢!
你调用 mp.Pool(10)
的那一刻你创建了 10 个处于“等待模式”的新进程,直到你给它们一些东西 运行,但是它们已经从你的进程中分叉出来所以任何改变局部变量不会影响它们
如果您想向他们传递信息,您需要:
在您调用它们时将其传递给它们(只需添加类似 pool.map(solver.solve, [(val, config.param) for val in val_list]
的内容,然后让 solve
拆分这些参数)
或者您需要使 config.param
成为一个可以在进程之间共享的变量,可能使用 multiprocessing.Value
像这样:
# config.py
import multiprocessing as mp
param = mp.Value("i", -1)
然后您可以像这样访问值:config.param.value
您可以覆盖 config.param 值,然后 mp.Pool()
启动如下。
# main.py
import multiprocessing as mp
import config, solver
config.param = 1 # trick is that
val_list = [None for i in range(3)]
pool = mp.Pool(10)
print('testing param: ', config.param)
results = pool.map(solver.solve, [val for val in val_list]) # multiprocessing
#results = [solver.solve(val) for val in val_list] # basic
我们需要 getter 和 setter 方法在 solver.py
中来保证 param
值的一致性。
#solver.py
import config
class Solver:
def __init__(self):
self._config = config.param
@property
def config(self):
return self._config
@config.setter
def config(self, cfgval):
self._config = cfgval
def solve(self, val):
# some computation using val and config.param
print('solver uses param:', self.config)
return None
然后您可以按照 main.py
.
param
和各种 val
执行计算
# main.py
import multiprocessing as mp
from solver import Solver
if __name__ == '__main__':
val_list = [None for i in range(3)]
pool = mp.Pool(10)
solver = Solver()
solver.config = 1
results = pool.map(solver.solve, [val for val in val_list]) # multiprocessing