【发布时间】:2015-09-18 18:23:47
【问题描述】:
我一直在尝试将包含多行(270 亿行)的大文件转换为 JSON。 Google Compute 建议我利用多线程来缩短写入时间。我已经从这里转换了我的代码:
import json
import progressbar
f = open('output.txt', 'r')
r = open('json.txt', 'w')
import math
num_permutations = (math.factorial(124)/math.factorial((124-5)))
main_bar = progressbar.ProgressBar(maxval=num_permutations, \
widgets=[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage(), progressbar.AdaptiveETA()])
main_bar.start()
m = 0
for lines in f:
x = lines[:-1].split(' ')
x = json.dumps(x)
x += '\n'
r.write(x)
m += 1
main_bar.update(m)
到这里:
import json
import progressbar
from Queue import Queue
import threading
q = Queue(maxsize=5)
def worker():
while True:
task = q.get()
r.write(task)
q.task_done()
for i in range(4):
t = threading.Thread(target=worker)
t.daemon = True
t.start()
f = open('output.txt', 'r')
r = open('teams.txt', 'w')
import math
num_permutations = (math.factorial(124)/math.factorial((124-5)))
main_bar = progressbar.ProgressBar(maxval=num_permutations, \
widgets=[progressbar.Bar('=', '[', ']'), ' ', progressbar.Percentage(), progressbar.AdaptiveETA()])
main_bar.start()
m = 0
for lines in f:
x = lines[:-1].split(' ')
x = json.dumps(x)
x += '\n'
q.put(x)
m += 1
main_bar.update(m)
我几乎直接从模块手册中复制了队列编码。
以前,整个脚本需要 2 天时间。现在是20天!我不太清楚为什么,谁能给我解释一下?
编辑:这可能被认为是 Python 全局解释器锁定 (GIL) 问题,但是,我认为并非如此 - 它不是计算密集型的,并且是 IO 瓶颈问题,来自线程文档:
如果您希望您的应用程序更好地利用计算 多核机资源,建议使用 多处理。但是,线程仍然是一个合适的模型,如果 您想同时运行多个 I/O 密集型任务。
我对此的理解是有限的,但我相信这是后者,即。一个 IO 绑定任务。这是我最初想使用多线程时的最初想法:计算被 IO 调用阻塞,可以将其放到单独的线程中以允许计算功能继续。
进一步编辑: 也许事实是我从 INPUT 获得了一个 IO 块,这就是它减慢速度的原因。关于如何有效地将“for”循环发送到单独的线程的任何想法?谢谢!
【问题讨论】:
-
您是否在数据集的一小部分上尝试过这个?你在什么样的环境下工作?
-
您只是增加了多个编写者共享对单个输出文件的访问权限的复杂性。如果每个线程都写入一个单独的文件,您可能会看到改进,尽管您最终可能仍希望连接各个文件。
-
无论你做什么,如此精细的分割可能会让通信成为应用程序的最大负担。为什么不一次发送几千行的块?为什么不在一次操作中写入几千行文件呢?
-
FWIW
factorial(a)/factorial(a-b) = reduce(operator.mul, range(a, a-b, -1)) -
“Python(至少是 CPython)有一个全局解释器锁,可以防止多个线程一次访问内存。” 毫无意义。 GIL 在 I/O 期间释放,C 扩展模块如 numpy、regex、lxml 也可能在 C 中长时间计算期间释放 GIL。GIL 是关于 Python 代码的;这与记忆无关。虽然我不认为多线程会以某种方式使硬盘更难工作(如果它们是这里的瓶颈的话)。
标签: python multithreading