Найти - Пользователи
Полная версия: Многопоточность
Начало » Python для новичков » Многопоточность
1
Moroznui
Добрый день, уважаемые Питонисты!
В первый раз сталкиваюсь с многопоточностью в Питоне и не могу понять решение одной проблемы.

Нужно функцию do_smth() вынести в отдельные потоки, но при этом порядок элементов в новом массиве не должен поменяться.

def do_smth(a):
            .......
            sleep(20)
new = []
for obj in objs:
            foo = do_smth(obj)
            new = new.append(foo)

т.е. на выходе new=do_smth(objs) or new=do_smth(objs)

Использовать очереди? Блокировки? Как? Мб кто-нибудь покажет пример кода.
Заранее спасибо!
dehun
разбивать на части. например на пополам.
In [25]: lst = range(0, 11)

In [26]: divider = len(lst)/2

In [27]: print lst
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

In [28]: print divider
5

In [29]: part1 = lst[divider:]

In [30]: part2 = lst[:divider]

In [31]: print part1
[5, 6, 7, 8, 9, 10]

In [32]: print part2
[0, 1, 2, 3, 4]
и потом конкатенировать результаты обработки. но теоретически приросту по производительности таким образом добится не удастся если конечно в do_smth не вызывается какаянить отправка по сети или запись на диск.
Moroznui
dehum, здесь разбиение не поможет.

Есть какая-то очень долгая операция над элементом массива(в моем случае do_smth() ), мы распараллеливаем их(выносим в отдельные потоки), но в таком случае я не могу гарантировать, что функция для первого элемента отработает раньше, чем для второго.
Если для N-ого элемента функция завершится быстрее - ей нужно будет подождать всех предыдуших.
Вопрос - где поставить лок? Или в питоне есть более изящное решение?
dehun
погуглил немного - http://dispy.sourceforge.net/
выглядит похоже на то что нужно.

если же в do_smth просто какието сетевые обработки то попробуйте грин треды.
например функцию imap или starmap из eventlet.GreenPool
http://eventlet.net/doc/modules/greenpool.html#eventlet.greenpool.GreenPool
dehun
дык мы вот получили парт1 и парт2.
теперь выполняем в отдельных потоках функции обработки этих данных.
получаем парт1резалт и парт2резалт. и делаем резалт = парт1резалт + парт2резалт.
ну естествено это после того как дождались обоих потоков обработки. дожидание обоих потоков я бы реализовал через join функцию.
но по перформансу это нам ничего не даст.
так как
CPython implementation detail: Due to the Global Interpreter Lock, in CPython only one thread can execute Python code at once (even though certain performance-oriented libraries might overcome this limitation). If you want your application to make better of use of the computational resources of multi-core machines, you are advised to use multiprocessing. However, threading is still an appropriate model if you want to run multiple I/O-bound tasks simultaneously.
reclosedev
Очень похоже, что нужна функция map из модуля multiprocessing (multiprocessing.Pool).

Для потоков есть недокументированный ThreadPool с тем же интерфейсом (обсуждение на StackOverflow)

pool = Pool(processes=4) 
results = pool.map(do_smth, objs)
fata1ex
Как насчет заносить результаты работы функций в словарь с правильными ключами/значениями, а потом сливать всё в список, упорядочивая результаты по ключу/значению соответственно.
dehun
только вызывать функцию там надо чуть хитрее.
у меня напрямую не получилось - погуглил - вот что нашёл
stackoverflow
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB