Experiments never fail s2

실험에 실패란 없다 블로그 시즌 2

Multiprocessing for pandas DataFrame apply

Pythonist - 2013년 12월 10일 7:26:45 오후

파이썬의 느린 for 루프를 map 혹은 list comprehension으로 바꾸면 더 빠르다는 사실을 알게된 뒤로 (파이콘 2013 다녀와서), 데이터가 좀 많다 싶은 분석은 pandas를 적극 이용하고 있다. 왠만한 자료구조도 리스트나 사전 대신 Series, DataFrame을 쓰면 훨씬 더 편하더라. for 루프는 가능하면 list comprehension 혹은 generator expression으로 바꾸고 apply 혹은 map으로 바꾸어 실행. 요즘 데이터과학 분야에 파이썬이 R을 대체하고 있다는 소식도 들리던데, 이게 다 pandas 때문인 듯.

pandas DataFrame을 잘 써먹는 방법 중 하나가 apply 함수를 적절히 이용하는 건데, 이것도 데이터가 많아지면 어쩔 수 없이 느려지더라. multiprocessing으로 나눠 돌리는 방법이 검색해보면 나올 줄 알았는데 안보여서 직접 만들어봤다.

apply 메쏘드를 적용할 DataFrame을 프로세서 수 만큼 쪼개고(np.array_split) 각각 해당 함수(square)로 apply 한 후, 다시 조립(pd.concat) 함. 요거 만들면서 몰랐던 파이썬 멀티프로세싱 팁.

  1. lambda, inner function, instance method는 멀티프로세싱 안된다. 함수를 피클링(pickling) 할 수 없다는 오류가 나는데, 실제로 각 분기된 프로세스가 해당 루틴을 돌기 위해 관련 객체들을 피클링할 때, 이런 함수들은 피클링이 안되는가 보다.

  2. pool.close() 해주지 않으면 잡다한 오류들과 함께 포크한 프로세스 정리도 안된다. 꼭 해줘야 함.

  3. 함수에 인수를 다양하게 줘야 할 경우, 위 코드에서 처럼 args로 포장해서 보내면 된다.

  4. 결과를 따로 받아서 정리하지 않아도 된다면 map 대신 map_async로 좀 더 빠르게 돌릴 수 있다.

듀얼코어 맥북에어에서 돌리면 딱 두배만큼 빨라진다. workers를 몇개로 적어줘도 딱 두배만큼만 빨라짐. 쿼드코어라면 4배 빨라진다고 우징님이 코맨트)해 주셨다. 이로써 맥프레로 바꿔야 할 이유가 하나 더 늘었다.


Posted by Hyungyong Kim (yong27)

태그(들): apply, dataframe, multiprocessing, pandas


comments powered by Disqus

« 내가 언제 어디서 뭘했는지에 대한 스마트한 기록, 모멘토(Momento)

위키에 정리하며 독서하기 »