3

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

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

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

1)使用“手动”创建线程from threading import Thread。这大约执行。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的a 。multiprocessing这大约需要。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)
  • 这两种使线程池慢 10 倍的方法之间有什么区别?
  • 对于我提出的不同方法或建议的任何替代建议?

非常感谢。

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

4

1 回答 1

3

Python 使用操作系统线程。虽然您对 CPU 密集型任务没有任何好处,但线程对于您的 IO 密集型任务来说很好。GIL,即Global Interpreter Lock,将为 IO 发布。

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

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

于 2013-06-07T19:28:24.300 回答