2015-03-26 2 views
1

Я проверяю следующий код, и я хотел бы, чтобы убедиться, если это правильно:многопоточных в Python (мой код правильный)

from threading import Thread 
import cPickle 

def get_user(start, end): 
    global users, vusers 
    for j in range(start,end): 
     if str(users[j]).find('@N') != -1: 
      vusers.append(users[j]) 


if __name__ == '__main__': 
    users = cPickle.load(open('nsid.dmp', 'r')) 
    vusers = [] 
    jobs = [Thread(target=get_user, args=(0,1839))\ 
     ,Thread(target=get_user, args=(1840,3679))\ 
     ,Thread(target=get_user, args=(3680,5519))\ 
     ,Thread(target=get_user, args=(5520,7359))\ 
     ,Thread(target=get_user, args=(7360,9199))\ 
     ,Thread(target=get_user, args=(9200,11039))\ 
     ,Thread(target=get_user, args=(11040,12879))\ 
     ,Thread(target=get_user, args=(12880,14719))\ 
     ,Thread(target=get_user, args=(14720,16559))\ 
     ,Thread(target=get_user, args=(16560,18399))\ 
     ,Thread(target=get_user, args=(18400,20239))\ 
     ,Thread(target=get_user, args=(20240,20079))\ 
     ,Thread(target=get_user, args=(22080,23919))\ 
     ,Thread(target=get_user, args=(23920,25759))\ 
     ,Thread(target=get_user, args=(25760,27599))\ 
     ,Thread(target=get_user, args=(27600,29439))] 
    for jb in jobs: 
     jb.start() 
    for jb in jobs: 
     jb.join() 
    vusers = list(set(vusers)) 
    out = open('validu.dmp', 'w') 
    cPickle.dump(vusers, out) 
    out.close() 

Так что я пытаюсь сделать, это запустить параллельно, функция get_user с различными диапазонами. Конечно, функция get_user сложнее, чем это, и есть много других условий для проверки, но когда я запускал код, я не мог видеть, что это более эффективное время. Что-то не так в моем коде, и это правильный способ написать многопоточную функцию? Если нет, как я могу заставить его работать параллельно?

+0

Если вы хотите, чтобы это было быстрее, попробуйте 'pypy'. Но если вы хотите понять, как сделать алгоритмы, выполняемые параллельно оптимально с использованием Python, используйте «многопроцессорность», как указано в ответах. Обратите внимание, что он вводит гораздо более сложную задачу, потому что вы должны отправлять входные данные и извлекать выходные данные и синтезировать их. –

+0

@BrianCain будет работать, если я заменил 'Thread' на multiprocessing.Process затем собирает данные, как описано здесь: \t http://stackoverflow.com/questions/8329974/can-i-get-a-return-value-from -multiprocessing-process – user9287

ответ

0

Я предполагаю, что вы хотите использовать множество людей по соображениям производительности. Если это так, вы, вероятно, должны использовать Process вместо Thread, вы можете узнать больше об ограничениях python Theads here.

Мне очень нравится multiprocess.Pool, который под капотом использует multiprocess.Process. Это позволяет вам запускать определенное количество процессов и задач очереди для них. Вот пример, используя pool.apply_async, но я также рассмотрю pool.map и pool.map_async.

from multiprocessing import Pool 

def get_user(users): 
    return [u for u in users if 'N' in u] 

def main(users): 
    vusers = [] 
    results = [] 

    N = 2 
    chunk = 200 

    pool = Pool(N) 
    for i in range(0, len(users), chunk): 
     r = pool.apply_async(get_user, args=(users[i:i + chunk],)) 
     results.append(r) 

    pool.close() 
    pool.join() 

    for r in results: 
     vusers.extend(r.get()) 

    return vusers 

if __name__ == '__main__': 
    import random 
    import string 
    users = [random.sample(string.ascii_uppercase, 5) for i in range(10000)] 
    vusers = main(users) 
+0

Я просто скопировал ваш код, и он не сработал. Я получил следующую ошибку: AttributeError: объект 'module' не имеет атрибута 'get_user'. Любое предложение исправить это? – user9287

+0

Python использует pickle для отправки информации между процессами. Я подозреваю, что pickle пытается импортировать функцию get_user в другой процесс и как-то запутывается. Попробуйте скопировать вышеуказанный код в новый файл с новым именем файла, тогда он должен работать нормально. –

+0

Большое вам спасибо! он работает так быстро. – user9287

1

Это не будет проходить параллельно из-за GIL. Я даже не уверен, будет ли он работать одновременно, потому что каждая целевая функция не выходит из GIL (т. Е. Нет системных вызовов и т. Д.).

Чтобы обойти GIL, вы должны использовать модуль многопроцессорности. Состояние совместного использования намного сложнее при многопроцессорной обработке, поэтому вам нужно будет реорганизовать код для сбора ответов, возвращаемых с каждого подпроцесса в основном потоке вашей программы.

+0

Что такое GIL? – Zizouz212

+0

Global Interpreter Замок См http://www.dabeaz.com/python/UnderstandingGIL.pdf или http://stackoverflow.com/questions/1294382/what-is-a-global-interpreter-lock-gil – Alexander

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