2013-06-07 3 views
3

моя проблема заключается в следующем: моему приложению необходимо загрузить несколько файлов одновременно на S3, используя библиотеку Boto в python. Я разработал 2 решения, но я не уверен в их последствиях. Некоторые соображения:python parallelism для загрузки файлов

  • Это будет работать на EC2 микро экземпляров, так низко памяти, низкая загрузка процессора
  • Обычно 1-10 файлы должны быть загружены на один раз, но может быть больше

Solutions , самый быстрый и самый медленный:

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 модуля. Это занимает около. 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) 
  • В чем разница между этими 2 подходами, что делает ThreadPool 10x медленнее?
  • Любые альтернативные предложения по различным подходам или рекомендациям в отношении того, что я придумал?

Большое спасибо.

EDIT: Я также просто понял, что multiprocessing имеет pool (которые, предположительно, создает новые процессы) и ThreadPool (которые, предположительно, создает рабочие нити). Я немного смущен.

ответ

2

Python использует потоки ОС. Хотя вы ничего не получаете для задач с привязкой к процессору, потоки отлично подходят для задачи, связанной с IO, как ваша. GIL, the Global Interpreter Lock, будет выпущен для IO.

Модуль multiprocessing предназначен для задач, связанных с процессором. В вашем случае он запускает 16 новых процессов. Это требует времени. Как правило, не имеет смысла увеличивать число рабочих/процессов, чем у вас есть процессоры. Мое правило: number_of_workers = number_of_cpus - 1. Кроме того, он связывается с использованием рассола для связи между процессами. Если вам нужно было делать много раз подряд, вы можете попытаться запустить несколько рабочих и сохранить их в живых и повторно использовать их снова и снова. Это может оправдать накладные расходы при запуске новых процессов, пока вы делаете заметные вычисления для каждой загрузки. Вам нужно профайл для вашего дела.

Третий вариант - перейти к асинхронному. Например, вы можете использовать Twisted. Затем вам нужно перестроить свой код, так как вам нужно работать с обратными вызовами.

+0

Спасибо за детали. Поскольку я буду запускать это на самых маленьких машинах EC2, может не иметь смысла использовать модуль «многопроцессорности». Поскольку вариант №1 был самым быстрым, какие подводные камни создают кучу потоков ОС - кроме того, что они дороги? Сколько потоков рекомендуется для чего-то подобного? (не представляется возможным создать 20 потоков, если у меня есть 20 загрузок ...) –

+0

Это зависит от множества факторов. Самое простое - это попробовать. Работайте без потоков, чем с 2, 4, 8, 16 .... Используйте разные размеры для ваших json-файлов. И, конечно же, попробуйте весь набор опций в разное время, для чего ожидайте, что другой сетевой трафик получит хорошую оценку, как все сложится в реальной жизни. Производительность - все о измерении. Я так часто ошибался в своих чувствах. Вам нужно генерировать жесткие цифры для реалистичных случаев. –

+0

Отлично. Ваш ответ повторяет [это] (http://stackoverflow.com/questions/481970/how-many-threads-is-too-many), на самом деле. Наконец, в [docs для объектов Thread] (http://docs.python.org/2/library/threading.html#thread-objects) упоминается, что «[поток] перестает быть живым, когда его метод run() прекращается». Если я правильно понимаю, мне не нужно явно очищать после того, как поток выполнил загрузку его файла, правильно? –

Смежные вопросы