GIL

GIL

CPython은 Global Interpreter Lock, 즉 GIL이라는 것을 사용한다. GIL은 일종의 뮤텍스로 복수의 네이티브 파이썬 스레드가 동시에 바이트코드를 실행하지 못하도록 하는 것이다. CPython의 메모리 관리 방식은 스레드-안전하지 못하기 때문에 이러한 방식의 락이 필요하다. 반대로 GIL을 도입하면서부터 다른 기능들은 GIL이 강제하는 부수효과에 의존하기 시작하기도 한다.

GIL은 양면성을 가지는데, 멀티스레드로 디자인된 CPython 프로그램이 멀티프로세서 시스템의 장점을 제대로 살리지 못하게 한다는 약점을 가지고 있다. (덕분에 파이썬 커뮤니티는 GIL을 강제하는 것 때문에 까이고 있다.)

하지만 다행히다 I/O나 이미지처리, NumPy등을 사용하는 고도의 수학계산과 같은 부분들은 GIL 영역의 밖이다. 따라서 GIL내에서 많은 시간을 소모해야하는 무거운 알고리듬을 사용하는 경우에는 짤없이 GIL이 병목의 원인이 된다.

그외에도 GIL은 때때로 병목이 아니면서도 전체적인 성능저하의 원인이 된다. 멀티코어 시스템에서의 시스템 콜 비용은 결코 만만한 것이 아니다. 싱글 코어 환경에서 함수 하나를 두 번 호출하는 것에 비해서 더블 코어 환경에서 함수 하나를 한 번씩 호출하는 것은 두 배의 비용이 든다. 그리고 GIL은 I/O 바운드 스레드가 CPU 바운드 스레드의 앞에 오도록 스케줄링한다. (결국 I/O작업이 프로그램의 흐름을 막아버린다)

그럼에도 불구하고 GIL은 메모리가 스레드-안전하지 않다는 가정하에서 (스레드-안전한 메모리 액세스를 위한 많은 처리들을 건너뛰는 방법으로) 싱글 스레드 환경에서의 빠른 속도를 얻어내었다. 실질적으로 GIL을 걷어낸 CPython에 대한 시도는 있어왔으나, 그 결과물들은 대체로 싱글 스레드 작업에서는 CPython의 처리 속도를 훨씬 밑도는 참담한 수준의 것들이었다.

진정한 멀티스레드 환경을 사용하려면 GIL에 의존하지 않는 다른 런타임, Jython이나 IronPython 과 같은 환경을 사용하면 멀티 프로세서 환경에서 멀티스레드를 사용하는데 있어 GIL에 의한 제약을 받지 않아도 된다.

Pypy는 순수 파이썬에 의한 CPython 구현으로 GIL에 동일하게 의존하고 있다. 대부분의 코드들이 Pypy에서 더 빠르게 동작할 수 있지만, GIL만큼은 동일하게 적용된다. 실행환경을 Pypy로 바꾸면서 멀티스레드의 병렬동작을 기대해서는 안된다. (하지만 CPython에서의 pypy로의 이행은 충분히 그럴만한 가치가 있다. 10여배 이상의 속도 증가를 가져올 수 있다!)