【发布时间】:2017-12-11 22:32:18
【问题描述】:
编辑:更新了环境信息(见第一部分)
环境
我使用的是 Python 2.7
Ubuntu 16.04
问题
我有一个应用程序,我已将其简化为三个阶段:
- 从多个数据源(HTTP 请求、系统信息等)收集数据
- 根据这些数据计算指标
- 以各种格式输出这些指标
这些阶段中的每一个都必须在进入下一个阶段之前完成,但是每个阶段都包含多个可以并行运行的子任务(我可以发送 3 个 HTTP 请求并在等待它们返回时读取系统日志)
我将阶段划分为模块,将子任务划分为子模块,所以我的项目层次结构如下所示:
+ datasources
|-- __init__.py
|-- data_one.py
|-- data_two.py
|-- data_three.py
+ metrics
|-- __init__.py
|-- metric_one.py
|-- metric_two.py
+ outputs
|-- output_one.py
|-- output_two.py
- app.py
app.py 看起来大致是这样(为简洁起见,伪代码):
import datasources
import metrics
import outputs
for datasource in dir(datasources):
datasource.refresh()
for metric in dir(metrics):
metric.calculate()
for output in dir(outputs):
output.dump()
(有额外的代码包装了dir 调用以忽略系统模块,还有异常处理等——但这是它的要点)
每个数据源子模块大致如下:
data = []
def refresh():
# Populate the "data" member somehow
data = [1, 2, 3]
return
每个指标子模块大致如下:
import datasources.data_one as data_one
import datasources.data_two as data_two
data = []
def calculate():
# Use the datasources to compute the metric
data = [sum(x) for x in zip(data_one, data_two)]
return
为了并行化第一阶段(数据源),我写了一些简单的东西,如下所示:
def run_thread(datasource):
datasource.refresh()
threads = []
for datasource in dir(datasources):
thread = threading.Thread(target=run_thread, args=(datasource))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
这可行,之后我可以计算任何指标并填充 datasources.x.data 属性
为了使第二阶段(指标)并行化,因为它较少依赖 I/O 而更多地依赖于 CPU,我觉得简单的线程实际上不会加快速度,我需要多处理模块才能利用的多个核心。我写了以下内容:
def run_pool(calculate):
calculate()
pool = multiprocessing.Pool()
pool.map(run_pool, [m.calculate for m in dir(metrics)]
pool.close()
pool.join()
这段代码运行了几秒钟(所以我认为它正在工作?)但是当我尝试时:
metrics.metric_one.data
它返回[],就像模块从未运行过一样
不知何故,通过使用多处理模块,它似乎在确定线程的范围,以便它们不再共享数据属性。我应该如何重写它,以便我可以并行计算每个指标,利用多个内核,但在完成后仍然可以访问数据?
【问题讨论】:
-
请参阅here 了解有关多处理和线程之间差异的更多信息
标签: python multithreading parallel-processing multiprocessing python-multiprocessing