>我有一个工作负载,它包含一个非常慢的查询,该查询返回了大量必须解析和计算的数据,所有这些都在一个循环中。基本上,它看起来像这样:
for x in lastTenYears
myData = DownloadData(x) # takes about ~40-50 [sec]
parsedData.append(ParseData(myData)) # takes another +30-60 [sec]
我相信您已经注意到,如果我可以在线程上运行数据解析,我可以在解析发生时下载下一批数据。
如何实现这种操作的并行性?
理想情况下,我希望始终下载 1 个线程,并有 N 个线程进行解析。下载部分实际上是对数据库的查询,所以有一堆并行的是不好的......
详细信息:
数据的解析受到严重的 CPU 限制,由
原始数学计算组成,没有其他内容。
使用 Python 3.7.4
1) 使用线程安全队列。在顶层定义
my_queue = Queue.FIFOQueue()
parsedData = []
2) 在第一个线程上,开始数据加载
my_queue.put(DownloadData(x))
在第二个线程上
if not (my_queue.empty()):
myData = my_queue.get()
parsedData.append(ParseData(myData))
如果您的程序受 CPU 限制,由于 GIL(全局解释器锁),您将很难在其他线程中执行任何其他操作。
以下是一篇文章的链接,可以帮助您理解该主题:https://opensource.com/article/17/4/grok-gil
在子流程中下载数据很可能是最好的方法。
很难说这是否以及实际上有多大帮助(因为我没有什么可测试的......),但你可以尝试一个multiprocessing.Pool
。它为您处理所有繁琐的工作,您可以自定义进程数量、块大小等。
from multiprocessing import Pool
def worker(x):
myData = DownloadData(x)
return ParseData(myData)
if __name__ == "__main__":
processes = None # defaults to os.cpu_count()
chunksize = 1
with Pool(processes) as pool:
parsedData = pool.map(worker, lastTenYears, chunksize)
在这里,我使用map
方法的示例,但根据您的需要,您可能需要使用imap
或map_async
.
问:如何实现这种操作的并行性?
第一步是要意识到,上面请求的用例不是[PARALLEL]
代码执行,而是无序一批资源使用策略限制执行严格的对序列:
Firsta-remote-[DB-Query]
(返回(引用)大量数据)Next-a-local-[CPU-process]
((引用)刚刚返回的大量数据)
第一个的延迟可以被屏蔽
(如果允许,但不允许- 由于不会使数据库主机过载),
第二个不的延迟(可以启动但下一个 I/O 绑定的数据库查询,但前提是不违反保留数据库机器的规则,但在轻微的工作负载下)。
我相信您已经注意到 ,如果我可以在线程上运行数据解析,我可以在解析发生时下载下一批数据。
现在是让事情变得清晰和合理的时候了:
事实:
A)
在python-GIL-lock控制的生态系统中,CPU绑定的任务永远不会在N
线程中运行得更快(从始至终,正如Guido ROSSUM所表达的那样),
因为GIL-lock强制执行重新[SERIAL]
化,所以"工作"的线程越多,实际上等待获取GIL-lock的线程就越多,然后他们"得到"它,但需要1 / ( N + 1 )
-时间的分数,由于 GIL-lock 警务再次纯[SERIAL]
,持续时间N * ( 30 - 60 ) [sec]
B )I/O 绑定任务卸载到基于完整进程的并发执行是没有意义的,因为 python 进程的完整副本(在 Windows 中也与子进程实例化期间用所有数据复制整个 python 解释器状态)
是没有意义的,因为有更智能的 I/O 绑定处理技术(其中 GIL-lock 不会受到太大伤害。
C)N-parsing : 1-querying
的整个概念主要是错误的- 最大可实现的目标是掩盖I/O进程的延迟(有意义),但在这里每个查询都采用这些所述~ 40-50 [sec]
因此在下次运行这些所述~ 40-50 [sec]
之前,这里将永远不存在第二个要解析的数据包, 因此
,在T0 + ~ 80~100 [sec]
之前,没有第二个工人会得到任何可以解析的东西- 所以人们可以梦想让 N-(未绑定)工作的愿望(但有他们但实际上在等待数据)是可能的,但非常反生产(对于N-(GIL-MUTEX-ED)-"WAITING"-AGENTS 来说更糟)。