2013-04-30 2 views
1

멀티 스레딩 내가하는 기능이 없다) 함수더 증가 파이썬 HDF5 구문 분석 기능

3) 하나의 문자열 함수 프로파일 링시

로 문자를 결합, 내가 계산의 대부분이 단계 # 2에 소요되는 것을 발견, 문자에 대한 ASCII 정수의 전환. 나는 다소 사용하여이 전화를 최적화 한 :

''.join([chr(x) for x in file[dataSetName].value]) 

내 분석 기능이 결합 된 CPU (문자 정수의 변환) 및 것 같다으로하지 내가 바인딩, 나는 더/덜 선형 속도를 얻을 것으로 예상/O 파싱에 집중 한 코어의 수를 늘려라. 하나의 파일을 순차적으로 파싱하려면 ~ 15 초가 걸립니다 ... (내 12 코어 머신에서) 10 개의 파일을 파싱하려면 10 개의 스레드를 사용하는 동안 ~ 150 초가 걸립니다. 즉, 전혀 개선되지 않은 것 같습니다. 내 스레드를 실행하려면 다음 코드를 사용했다

은 :

threads=[] 
    timer=[] 
    threadNumber=10 
    for i,d in enumerate(sortedDirSet): 
     timer.append(time.time()) 
    # self.loadFile(d,i) 
     threads.append(Thread(target=self.loadFileargs=(d,i))) 
     threads[-1].start() 
     if(i%threadNumber==0): 
      for i2,t in enumerate(threads): 
       t.join() 
       print(time.time()-timer[i2]) 
      timer=[] 
      threads=[] 

    for t in threads: 
     t.join() 

어떤 도움을 크게 감상 할 수있다.

+3

아마도 GIL을 실행 중입니다. http://wiki.python.org/moin/GlobalInterpreterLock. –

답변

4

(예 : multiprocessing) 하위 프로세스를 생성하지 않으면 파이썬에서 GIL로 인해 여러 코어를 사용할 수 없습니다. 따라서 은 CPU 바인딩 작업을위한 스레드를 생성하여 성능 향상을 위해이되지 않습니다.


여기 multiprocessingqueue을 사용하여 스크립트의 예 :

from Queue import Empty # <-- only needed to catch Exception 
from multiprocessing import Process, Queue, cpu_count 

def loadFile(d, i, queue): 
    # some other stuff 
    queue.put(result) 

if name == "main": 
    queue = Queue() 
    no = cpu_count() 
    processes = [] 

    for i,d in enumerate(sortedDirSet): 
     p = Process(target=self.loadFile, args=(d, i, queue)) 
     p.start() 
     processes.append(p) 

     if i % no == 0: 
      for p in processes: 
       p.join() 
      processes = [] 

    for p in processes: 
     p.join() 

    results = [] 
    while True: 
     try: 
      # False means "don't wait when Empty, throw an exception instead" 
      data = queue.get(False) 
      results.append(data) 
     except Empty: 
      break 

    # You have all the data, do something with it 

다른 (더 복잡한) 방법은 pipe 대신 queue 사용하는 것입니다.

프로세스를 생성 한 다음 작업 대기열을 생성하고 (pipe을 통해) 하위 프로세스로 전송하므로 (매번 프로세스를 생성 할 필요가 없음)보다 효율적입니다. 그러나 이것은 훨씬 더 복잡 할 것입니다. 그래서 그것을 그대로 두겠습니다.

+0

폭발.GIL은 멀티 스레딩의 유용성 95 %를 보여줍니다. 처음에는 다중 처리 .imap을 사용하려고 시도했지만 freeze_support 오류를 해결하는 것이 어려웠습니다. 또한 클래스 메서드 내에서 __name__ == '__main__'을 사용하는 올바른 방법을 찾지 못했습니다. 어떤 힌트? – PaulD

+0

@ PaulD 글쎄, 파이썬은 CPU 바인딩 작업을 위해 처음에는 설계되지 않았습니다. 그러나 스레드는 I/O 바운드 작업과 잘 작동합니다. 그리고 나는 대답을 업데이트했다. (그렇게하는 방법이지만, 분명히 당신의 상황에 달려있다.) – freakish

+0

예를 들어 주셔서 감사합니다. 내가 가진 문제는 1) 내 프로세스 산란 포인트가 main에 없다 ... 클래스 메소드에있다. 또한 생성 된 메서드는 클래스 멤버 변수를 사용합니다. 이 경우 다중 처리를 사용할 수 없다고 생각합니까? – PaulD

0

그의 대답에 괴물이 맞으면, 그것은 당신의 노력을 방해하는 길일 것입니다.

파이썬 3을 사용하려면 concurrent.futures을 사용하면됩니다. PyPy가이 기능을 백 포트한다고 생각합니다. 대규모 무작위 목록 (

''.join(map(chr, file[dataSetName].value)) 

내 테스트 :지도와

''.join([chr(x) for x in file[dataSetName].value]) 

:

또한, 당신은 당신의 지능형리스트를 대체하여 코드에서 조금 더 속도를 이크 수)는 위의 코드를 사용하여 목록 이해력을 사용하여 15.73s를, map을 사용하여 12.44s를 나타냅니다.