用于上传文件的python并行性

时间:2013-06-07 15:13:54

标签: python multithreading threadpool

我的问题如下:我的应用程序需要使用python中的Boto库同时将多个文件上传到S3。我已经找到了2个解决方案,但我不确定每个解决方案的含义。一些注意事项:

  • 这将在EC2微实例上运行,因此内存不足,CPU占用率低
  • 通常需要一次上传1-10个文件,但可以更多

解决方案,最快,然后最慢:

1)使用from threading import Thread“手动”创建线程。这在aprox中执行。 0.02秒。

from boto.s3.connection import S3Connection
from threading import Thread
import time

filenames = ['1.json', '2.json', '3.json', '4.json', '5.json', '6.json', '7.json', '8.json', '9.json', '10.json']
def upload(myfile):
        conn = S3Connection(aws_access_key_id=AWS_KEY, aws_secret_access_key=AWS_SECRET)
        bucket = conn.get_bucket("parallel_upload_tests")
        key = bucket.new_key(myfile).set_contents_from_string('some content')
        return myfile

for fname in filenames:
        t = Thread(target = upload, args=(fname,)).start()

2)使用ThreadPool模块中的multiprocessing。这需要aprox。执行0.3秒(几乎慢10倍)

from boto.s3.connection import S3Connection
from multiprocessing.pool import ThreadPool
import time

filenames = ['1.json', '2.json', '3.json', '4.json', '5.json', '6.json', '7.json', '8.json', '9.json', '10.json']
def upload(myfile):
        conn = S3Connection(aws_access_key_id=AWS_KEY, aws_secret_access_key=AWS_SECRET)
        bucket = conn.get_bucket("parallel_upload_tests")
        key = bucket.new_key(myfile).set_contents_from_string('some content')
        return myfile

pool = ThreadPool(processes=16)
pool.map(upload, filenames)
  • 这两种方法有什么区别使线程池10x变慢?
  • 针对我提出的不同方法或建议的任何其他建议?

非常感谢。

编辑:我也刚刚意识到multiprocessing有一个pool(可能会创建新进程)和ThreadPool(可能会创建线程工作者)。我有点困惑。

1 个答案:

答案 0 :(得分:2)

Python使用OS线程。虽然你没有为CPU绑定任务获得任何东西,但线程对于你的IO绑定任务来说很好。 GIL, the Global Interpreter Lock,将发布IO用于发布。

multiprocessing模块专为CPU绑定任务而设计。在您的情况下,它启动16个新进程。这需要时间。通常情况下,创建更多的工作者/进程比拥有CPU更有意义。我的经验法则是number_of_workers = number_of_cpus - 1。此外,它使用pickle进行通信以进行进程之间的通信。如果您需要连续多次上传,您可能希望尝试启动多个工作程序并使其保持活动状态并一遍又一遍地重复使用它们。只要您为每次上传做了明显的计算,这可能证明启动新进程的开销是合理的。您需要根据您的情况对此进行分析。

第三种选择是异步。例如,您可以使用Twisted。然后,您需要重新构建代码,因为您需要使用回调。