[Python] GIL
in Python
Global Interpreter Lock (GIL)
CPython(파이썬의 표준 구현체)에서 파이썬 코드(bytecode)를 실행할 때 단 하나의 스레드만 접근할 수 있도록 제한하는 mutex
CPython 에서의 메모리 관리: Reference Counting
CPython 에서는 reference 의 갯수를 세는 방법으로 메모리를 관리함.
sys.getrefercount
라는 메소드를 이용해서 특정 object 에 대해 python 이 세고있는 reference 갯수를 확인할 수 있음
import sys
a = []
b = a
sys.getrefercount(a) # print 3
왜 3개냐
- a가 처음 만들어졌을 때
- b에 a를 할당했을 때
getrefercount
메소드 인자로 들어갔을 때
이 갯수가 0이 되면 CPython 이 알아서 메모리를 회수함
reference counting 으로 인한 문제점
- CPython은 생성된 객체에 대해 reference 를 세어가면서 메모리 관리를 함
- 다수의 스레드 사용으로 reference counting 과정에서 race condition 이 생길 수 있음
- CPython 은 C 로 구현되어 있으므로 race condition 을 막기 위해서는 mutex 를 사용하면 됨
- 각 객체마다 mutex 를 사용하는 것은 큰 성능 저하로 이어지고 deadlock 발생 가능성도 있음
CPython 의 선택
- mutex 를 통해 각 객체에 대해 락을 걸지말고, 그냥 인터프리터 자체에 락을 걸자
- 이것이 GIL (Global Interpreter Lock)
- 이로 인해 하나의 파이썬 코드에 대해서 하나의 스레드만 동작하게 됨
threading
모듈을 사용해도 성능 개선은 커녕 오히려 성능 저하가 일어나는 경우가 있는데, GIL 때문임- 파이썬 창시자 귀도는 “단일 스레드 프로그램에서 성능 저하 없이 GIL 의 문제점을 개선할 수 있으면 반영하겠다.” 라고 말했지만, 현재까지 그런 일은 일어나지 않았음
파이썬에서 병렬 처리
- 병렬처리가 필요한 경우
asyncio
혹은multiprocessing
을 이용 - CPython 대신 다른 구현체를 이용하는 것도 방법(PyPy, Jython, etc.)