[Python] GIL 과 multiprocessing Develop Tip

간혹 파이썬을 이야기 하면서 구체적으로 사용해 보지도 않고
GIL 때문에 멀티쓰레드 작업에 문제가 많아... 라는 이야기들이 있습니다.

우선 GIL 은 Global Interpreter Lock 으로써 멀티쓰레드를 사용하더라도
GIL 때문에 C의 pthread 와 같은 동시성 프로그램을 제대로 할 수 없다는 데
문제가 있습니다.

이것을 아주 쉽게 발표자료를 만들어주신 
40페이지 정도부터 보시면 정말 딱 보고 알 수 있을 정도로
쉽게 설명을 해 주셨습니다.

더불어 파이썬의 장점도 쉽게 설명되어 있습니다.

또한 일전에 살펴본 "Queue를 이용한 쓰레드 풀의 사용방법"에서와 
같이 작업을 할 때 문제가 있을 수 있습니다.

따라서 기존의 Thread 작업이 있었다면,
이를 거의 동일한 인터페이스의 프로세스 모델로 작업을 할 수 있는
multiprocessing 모듈이 있고 이를 이용하여 아래와 같이 작업을 할 수 있습니다.


#!/usr/bin/env python
#coding=utf8

##########################################################################################
import os
import time
import multiprocessing
import ctypes

##########################################################################################
class MultiProcess(multiprocessing.Process):
def __init__(self, mprun_break, p1, p2):
multiprocessing.Process.__init__(self)
self.mprun_break = mprun_break
self.p1 = p1
self.p2 = p2
def run(self):
try:
cnt = 0
while not self.mprun_break.value:
print "[%s:%s] p1=%s,p2=%s" % (os.getpid(), cnt, self.p1, self.p2)
time.sleep(1)
cnt += 1
finally:
print "[%s] before terminate: p1=%s,p2=%s" % (os.getpid(), self.p1, self.p2)

##########################################################################################
def test():
mps = list()
mm = multiprocessing.Manager()
mprun_break = mm.Value(ctypes.c_bool, False)
for i in range(3):
mp = MultiProcess(mprun_break, i,str(i))
mp.daemon = True
mps.append(mp)
print ">>> in main before start!!!"
for mp in mps:
mp.start()

time.sleep(3)
# 아래의 terminate는 MultiProcess의 finally: 코드가 수행안됨
# print ">>> in main before terminate!!!"
# for mp in mps:
# mp.terminate()

mprun_break.value = True
print ">>> in main before join!!!"
for mp in mps:
mp.join()

print ">>> Main Done!"

##########################################################################################
if __name__=='__main__':
test()

이제 돌려봅니다.

위와 같이 세개의 PID를 갖는 MultiProcess 클래스 작업이 3번 수행되었고 정상적으로 
while loop도 끝나 before terminate 를 출력하면 종료됩니다.

multiprocessing.Manager 를 이용하여 공유되는 Bool 형식의 mprun_break 공동 
변수를 사용하여 가능한 것이지요.

그런데 만약,

위와 같이 terminate()를 직접 호출하고 결과를 돌려보면

위와 같이 작업하던 중간에 프로세스가 종료됨을 알 수 있습니다.

어느 분께는 도움이 되셨기를...

핑백

  • 20151019 | gumdaeng 2015-10-19 20:37:55 #

    ... GIL로 구현되어 있어서 느리다고 함. References: [1] [Python] GIL 과 multiprocessing, 지훈현서아빠, http://mcchae.egloos.com/11099578 [2] 하용호, 2011 H3 컨퍼런스-파이썬으로 클라우드 하고 싶어요, http://www.slideshare.net/yongho/ ... more

덧글

  • 도움받은이 2016/12/29 17:08 # 삭제 답글

    동영상을 보여주면서 센서 데이터를 읽어야하는 멀티프로세싱을 해야했는데, terminate를 쓰지 않아 덕분에 아주 깔끔하게 동기화하고 갑자기 죽지 않아서 끝나기전 해야할 일을 finally에서 잘 기술해 구현했네요. 감사합니다.
  • 지훈현서아빠 2016/12/29 17:50 #

    도움이 되셨다니 저의 보람입니다. ^^
  • 지나가다가 2017/04/13 10:03 # 삭제 답글

    한쪽에 sleep 죽이고 해보셨나요? 해보면 한번 sleep된 녀석은 절대 다시 스케쥴링 되지 않더군요.
댓글 입력 영역

구글애드텍스트