首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多线程文件复制比多核CPU上的单个线程慢得多。

多线程文件复制比多核CPU上的单个线程慢得多。
EN

Stack Overflow用户
提问于 2011-12-21 03:37:18
回答 6查看 6.7K关注 0票数 5

我试图用Python编写一个多线程程序,以加速(1000以下) .csv文件的复制。多线程代码的运行速度甚至比顺序方法还要慢。我用profile.py计时了代码。我肯定我做错了什么,但我不确定是什么。

环境:

  • 四核CPU.
  • 2硬盘驱动器,一个包含源文件.另一个是destination.
  • 1000 csv文件,大小从几KB到10 MB.

的方法:

我将所有文件路径放入一个队列中,创建4-8个工作线程,从队列中提取文件路径并复制指定的文件。在任何情况下,多线程代码都不会更快:

seconds

  • threaded
  • 顺序复制需要150-160秒

我假设这是一个I/O绑定的任务,所以多线程应该有助于操作速度。

代码:

代码语言:javascript
复制
    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()')
EN

回答 6

Stack Overflow用户

发布于 2011-12-21 03:39:28

当然比较慢。硬盘必须不断地在文件之间寻找。你认为多线程会使这个任务更快的想法是完全没有道理的。限制速度是从磁盘读取数据或将数据写入磁盘的速度,而从一个文件到另一个文件的每一次查找都浪费了传输数据的时间。

票数 10
EN

Stack Overflow用户

发布于 2017-08-05 21:00:49

我想我可以验证这是磁盘I/O情况。我在我的机器上做了一个类似的测试,从一个非常快的网络服务器复制回自己,仅仅使用上面的代码(4个线程),我就看到了将近1:1的速度增长。我的测试是复制总计16.5g的4137个文件:

代码语言:javascript
复制
Sequential copy was 572.033 seconds.
Threaded (4) copy was 180.093 seconds.
Threaded (10) copy was 110.155
Threaded (20) copy was 86.745
Threaded (40) copy was 87.761

正如你所看到的,当你进入越来越高的线程数时,会有一点“下降”,但是在4个线程时,我的速度有了很大的提高。我在一台非常快的计算机上,有一个非常快的网络连接,所以我想我可以安全地假设你达到了I/O的极限。

尽管如此,看看我在这里得到的共鸣:Python multiprocess/multithreading to speed up file copying。我还没有机会尝试这段代码,但是gevent可能会更快一些。

  • Spencer
票数 2
EN

Stack Overflow用户

发布于 2011-12-21 03:43:36

我假设这是一个更多的I/O绑定任务,多线程应该帮助操作速度,我的方法有问题吗?!

是。

  1. 标点符号太多了。只有一个。"?“appropriate.
  2. Your的假设是错误的吗。多线程帮助CPU绑定(有时)。它永远帮不了I/O的束缚。从来没有。

进程中的所有线程必须等待,而一个线程执行I/O。

还是coroutine来做这项工作?!

不是的。

如果你想做大量的I/O,你需要很多的过程。

如果你要复制1000个文件,你需要很多,很多进程。每个进程都复制一些文件。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8584797

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档