【发布时间】:2012-01-24 23:14:33
【问题描述】:
我正在尝试用 Python 编写一个多线程程序来加速复制(少于 1000 个).csv 文件。多线程代码的运行速度甚至比顺序方法还要慢。我用profile.py 为代码计时。我确定我一定做错了什么,但我不确定是什么。
环境:
- 四核 CPU。
- 2 个硬盘驱动器,其中一个包含源文件。另一个是目的地。
- 1000 个 csv 文件,大小从几 KB 到 10 MB 不等。
方法:
我把所有的文件路径放在一个Queue中,并创建4-8个工作线程从队列中拉取文件路径并复制指定的文件。在任何情况下,多线程代码都不会更快:
- 连续复制需要 150-160 秒
- 线程复制需要超过 230 秒
我假设这是一个 I/O 绑定任务,所以多线程应该有助于提高操作速度。
守则:
import Queue
import threading
import cStringIO
import os
import shutil
import timeit # time the code exec with gc disable
import glob # file wildcards list, glob.glob('*.py')
import profile #
fileQueue = Queue.Queue() # global
srcPath = 'C:\\temp'
destPath = 'D:\\temp'
tcnt = 0
ttotal = 0
def CopyWorker():
while True:
fileName = fileQueue.get()
fileQueue.task_done()
shutil.copy(fileName, destPath)
#tcnt += 1
print 'copied: ', tcnt, ' of ', ttotal
def threadWorkerCopy(fileNameList):
print 'threadWorkerCopy: ', len(fileNameList)
ttotal = len(fileNameList)
for i in range(4):
t = threading.Thread(target=CopyWorker)
t.daemon = True
t.start()
for fileName in fileNameList:
fileQueue.put(fileName)
fileQueue.join()
def sequentialCopy(fileNameList):
#around 160.446 seconds, 152 seconds
print 'sequentialCopy: ', len(fileNameList)
cnt = 0
ctotal = len(fileNameList)
for fileName in fileNameList:
shutil.copy(fileName, destPath)
cnt += 1
print 'copied: ', cnt, ' of ', ctotal
def main():
print 'this is main method'
fileCount = 0
fileList = glob.glob(srcPath + '\\' + '*.csv')
#sequentialCopy(fileList)
threadWorkerCopy(fileList)
if __name__ == '__main__':
profile.run('main()')
【问题讨论】:
-
您说“我认为它受 I/O 限制”然后说“多线程应该有助于提高操作速度”。你看错了。 I/O bound 意味着它受 I/O 约束,而不是 CPU。如果它受 CPU 限制,多线程会有所帮助。
-
当然它更慢 - 您是否为每个要生成的线程设置了一组硬盘驱动器头?
-
与
robocopy C:\temp D:\temp *.csv比较 -
谢谢大家,多多了解真好!
标签: python multithreading file copy queue