Python Queue - потоки связаны только с одним ядром - PullRequest
2 голосов
/ 13 октября 2010

Я написал скрипт на python, который: 1. отправляет поисковые запросы 2. ожидает результатов 3. анализирует возвращаемые результаты (XML)

Я использовал модули Threading и Queue для параллельного выполнения этого (5работники).
Это прекрасно работает для части запросов, потому что я могу отправлять несколько поисковых запросов и иметь дело с результатами по мере их поступления.
Однако, похоже, что все мои потоки связаны с одним и тем же ядром.Это становится очевидным, когда он попадает в ту часть, где обрабатывает XML (интенсивно использует процессор).

Кто-нибудь еще сталкивался с этой проблемой?Я что-то упускаю концептуально?

Кроме того, я размышлял над идеей иметь две отдельные рабочие очереди, одну для выполнения запросов и одну для анализа XML.Как и сейчас, один работник будет делать оба в серийном режиме.Я не уверен, что это купит меня, если что-нибудь.Любая помощь будет принята с благодарностью.

Вот код: (удаленные данные удалены)

def addWork(source_list):
    for item in source_list:
        #print "adding: '%s'"%(item)
        work_queue.put(item)

def doWork(thread_id):
    while 1:
        try:
            gw = work_queue.get(block=False)
        except Queue.Empty:
            #print "thread '%d' is terminating..."%(thread_id)
            sys.exit() # no more work in the queue for this thread, die quietly

    ##Here is where i make the call to the REST API
    ##Here is were i wait for the results
    ##Here is where i parse the XML results and dump the data into a "global" dict

#MAIN
producer_thread = Thread(target=addWork, args=(sources,))
producer_thread.start() # start the thread (ie call the target/function)
producer_thread.join() # wait for thread/target function to terminate(block)

#start the consumers
for i in range(5):
    consumer_thread = Thread(target=doWork, args=(i,))
    consumer_thread.start()
    thread_list.append(consumer_thread)

for thread in thread_list:
    thread.join()

Ответы [ 2 ]

4 голосов
/ 13 октября 2010

Это побочный продукт того, как CPython обрабатывает потоки.В интернете бесконечные дискуссии (поиск GIL), но решение состоит в том, чтобы использовать модуль multiprocessing вместо threading. Многопроцессорность построен с почти таким же интерфейсом (и структурами синхронизации, поэтому вы все еще можете использовать очереди) в качестве потоков.Он просто дает каждому потоку свой собственный весь процесс, что позволяет избежать GIL и принудительной сериализации параллельных рабочих нагрузок.

2 голосов
/ 13 октября 2010

Используя CPython, ваши потоки никогда не будут работать параллельно в двух разных ядрах.Посмотрите информацию о Global Interpreter Lock (GIL) .

По сути, существует блокировка взаимного исключения, защищающая действительную часть интерпретатора, поэтому никакие два потока не могут вычислять параллельно.Потоки для задач ввода-вывода будут работать нормально из-за блокировки.

edit : если вы хотите полностью использовать преимущества нескольких ядер, вам нужно использовать несколько процессов.Есть много статей на эту тему, я пытаюсь найти одну для вас, я помню, это было здорово, но я не могу найти ее = /.

Как предложил Натон, вы можете использовать модуль многопроцессорной обработки.Существуют инструменты, которые помогут вам обмениваться объектами между процессами (взгляните на POSH, Python Object Sharing).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...