Я пытаюсь написать многопоточную программу на Python, чтобы ускорить копирование (до 1000) .csv файлов. Многопоточный код работает даже медленнее, чем последовательный подход. Я рассчитал код с profile.py
. Я уверен, что я должен делать что-то не так, но я не уверен, что.
Окружающая среда:
- Четырехъядерный процессор.
- 2 жестких диска, один из которых содержит исходные файлы. Другой пункт назначения.
- 1000 CSV-файлов размером от нескольких КБ до 10 МБ.
Подход:
Я помещаю все пути к файлам в очередь и создаю 4-8 рабочих потоков, извлекаю пути к файлам из очереди и копирую указанный файл. Ни в коем случае многопоточный код не работает быстрее:
- последовательное копирование занимает 150-160 секунд
- многопоточное копирование занимает более 230 секунд
Я предполагаю, что это задача, связанная с вводом / выводом, поэтому многопоточность должна помочь скорости работы.
Код:
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()')