2013-04-30 3 views
4

여러 스레드를 사용하여 디렉토리의 모든 파일을 병렬 처리합니다. 스레드가 살아있는 것처럼 보이고 프로세스의 스레드 수가 1K 정도가 될 때까지 올라가서 thread.error can't start new thread 오류가 발생하는 것을 제외하면 모두 잘 작동합니다. 이 오류는 스레드 수에 대한 OS 수준 한계로 인해 발생합니다. 버그가 살아있는 스레드를 유지하고있는 곳을 알아낼 수 없습니다. 어떤 생각? 여기 내 코드의 최소한의 버전입니다.새 스레드를 시작할 수 없습니다.

class Worker(Thread): 
    def __init__(self, tasks): 
     Thread.__init__(self) 
     self.tasks = tasks 
     self.daemon = True 
     self.start() 

def run(self): 
    while True: 
     func, args, kargs = self.tasks.get() 
     try: 
      func(*args, **kargs) 
     except Exception, e: print e 
     self.tasks.task_done() 


class ThreadPool: 
    def __init__(self, num_threads): 
     self.tasks = Queue(num_threads) 
     for _ in range(num_threads): Worker(self.tasks) 

    def add_task(self, func, *args, **kargs): 
     self.tasks.put((func, args, kargs)) 

    def wait_completion(self): 
     self.tasks.join() 


def foo(filename) 
    pool = ThreadPool(32) 
    iterable_data = process_file(filename) 

    for data in iterable_data: 
     pool.add_task(some_function, data) 
    pool.wait_completion() 

files = os.listdir(directory) 
for file in files: 
    foo(file) 

답변

3

모든 파일에 대해 32 개의 스레드로 새 ThreadPool을 시작합니다. 파일 수가 많으면 스레드 수가 많을 것입니다. 그리고 한번만 스레드가 CPython에서 파이썬 바이트 코드를 실행할 수 있기 때문에 (글로벌 인터프리터 잠금 때문에) 반드시 빠른 것은 아닙니다.

foo() 함수 외부에서 ThreadPool 생성을 이동하십시오.

+3

다중 프로세스 (스레드가 I/O 바운드 코드에 적합)가 필요하지 않은 경우 자신의 스레드 풀을 만들 필요가 없습니다 :'from multiprocessing.pool import ThreadPool'. foo() 함수 밖에서 풀을 움직이면 문제가 해결됩니다. – bj0

+0

작업에 네트워크 호출 (HTTP)이 포함되어 있기 때문에 스레드를 사용하고 있습니다. '멀티 프로세싱 '을 사용하면 많은 도움이되지 않습니다. – leonsas

+0

@ bj0 foo() 외부에서 풀을 이동하는 것이 효과적입니다. 대답을 게시하여 받아 들일 수 있습니다. 감사! – leonsas

관련 문제