본문 바로가기

프로그래밍언어/Python

[Python] GIL (Global Interpreter Lock)

반응형

파이썬에서 멀티쓰레딩과 같이 동시성, 병렬 작업 등에 대한 공부를 하다보면 항상 나오는 단어가 있다. 바로 GIL 이다. GIL 은 Global Interpreter Lock 의 줄임말로 파이썬 인터프리터의 동작과 관련된 용어이다.

GIL 이 무엇인지 대략적으로는 알고있지만 자세하게, 그래서 실제 멀티 쓰레딩, 멀티 코어에서 어떻게 동작하는지는 알지 못해서 이번 기회에 좀 더 알아보려 한다.

1. GIL

GIL 은 일종의 mutex 이다. 인터프리터에서 thread-safe 하지 않은 객체들에 대한 접근을 막기위해 사용하는 쓰레드 mutex 이다. 인터프리터에서 한 번에 하나의 쓰레드만 실행하도록 하여 쓰레드들 간의 동작에 동기화를 맞추도록 하는 동작 원리이다. 파이썬의 경우 CPython 인터프리터가 GIL 을 사용한다.

GIL 을 사용하는 인터프리터 프로세스는 GIL 을 하나씩 가지고 있어서 쓰레드의 동작을 관리하도록 한다. GIL 을 사용하면 한번에 하나의 native thread 만 동작이 되는데 이 말은 멀티 코어 프로세스 환경에서도 각 코어마다 다른 쓰레드가 실행되어 병렬적으로 동작하는 것이 아니라 하나의 쓰레드만 실행된다는 의미이다.

 

※ mutex
뮤텍스는 멀티 프로그래밍 (멀티 프로세스, 멀티 쓰레드) 에서 공유 자원을 안전하게 관리하기 위해 상호 배제로 동작하도록 하기 위한 기법이다.

뮤텍스는 1개의 lock 을 가지는 개념으로 일종의 key 역할을 한다. 프로세스가 동작 시에 뮤텍스를 얻은 프로세스만이 임계 영역에 들어가서 자원에 접근할 수 있도록 한다. 이때 공유 자원을 점유하면 뮤텍스를 lock 하여 다른 프로세스가 뮤텍스를 가질 수 없도록 한다. 뮤텍스가 lock 이 되어있는 상태에서 다른 프로세스가 뮤텍스를 요청하면, 이를 점유하고 있는 프로세스의 작업이 끝나서 뮤텍스가 release 될 때까지 대기해야한다.

2. GIL 을 사용하는 이유

파이썬에서 GIL 을 사용하는 가장 큰 이유는 메모리 관리를 위해서이다.

 

파이썬에서 모든 것은 객체이다. 그러한 객체들은 Reference Count 를 통해서 관리된다. 파이썬의 GC 는 Reference Count 를 확인하여 0 이 되면 해당 객체를 메모리에서 삭제시킨다.

이와 같은 메모리 관리 환경에서는 여러 개의 쓰레드가 파이썬 인터프리터를 동시에 실행하는 경우 race condition 이 발생할 수 있다. 그렇게 되면 Reference Count 가 올바르게 관리되지 못할 수 있고, 이로 인해서 GC 가 제대로 작동하지 않아서 메모리 문제가 발생할 수 있다. 이러한 문제를 해결하기 위하여 GIL 을 파이썬 객체에 대한 mutex 로 사용하는 것이다.

3. GIL 과 멀티 쓰레딩

GIL 을 사용하면 병렬 처리 시에 실행할 수 있는 쓰레드의 개수를 하나로 제한하기 때문에 CPU 연산이 많은 작업을 할 때 멀티 쓰레딩은 성능이 떨어진다. 하나의 쓰레드만 실행하기 때문에 병렬 실행은 불가능한데, 쓰레드를 교체하면서 발생하는 context switching 비용만 발생하기 때문이다.

하지만 CPU 연산이 아닌 외부 연산 (I/O, sleep 등) 이 많이 포함된 작업을 수행하는 경우에는 멀티 쓰레딩이 싱글 쓰레딩보다 더 좋은 성능을 보인다. CPU 연산의 경우에는 작업을 하던 도중에 쓰레드를 교체하면서 context switching 비용이 발생했지만, 외부 연산의 경우 CPU 는 아무것도 하지 않고 대기하기 때문에 이때 context switching 을 시도하여 CPU 가 다른 작업을 수행하게 하면 실행 효율에 손실이 없다.

4. CPU 연산 병렬 처리

1) 멀티 프로세싱

멀티 프로세싱은 멀티 쓰레딩과 다르게 쓰레드가 아닌 아예 새로운 프로세스를 생성하여 실행하는 것이다. 이 경우에는 프로세스가 독자적인 메모리 공간을 가지게 되어서 프로세스 간에는 race condition 이 발생하지 않는다. 각 프로세스 내에 별개의 GIL 이 존재하고 이들은 프로세스 내부에서만 동작한다고 생각하면 된다. 그렇기 때문에 멀티 프로세싱의 경우 여러 작업을 병렬적으로 수행할 수 있다.

2) 인터프리터 교체

위에서 설명한 것처럼 CPython 인터프리터는 GIL 을 사용하는 인터프리터이다. 만약 CPU 작업을 병렬적으로 실행하고자 한다면 GIL 을 사용하지 않는 인터프리터 구현체를 찾아서 사용하면 된다. 파이썬의 인터프리터 중에는 Jython 등이 GIL 을 사용하지 않는다. 하지만 이러한 방법은 잘 사용되지 않는 방법이기 때문에 권장하지는 않는다.

[Reference]

- https://en.wikipedia.org/wiki/Global_interpreter_lock

 

Global interpreter lock - Wikipedia

From Wikipedia, the free encyclopedia Jump to navigation Jump to search Mechanism that ensures threads are not executed in parallel A global interpreter lock (GIL) is a mechanism used in computer-language interpreters to synchronize the execution of thread

en.wikipedia.org

https://it-eldorado.tistory.com/160

 

[Python] GIL (Global Interpreter Lock) 이해하기

이번 포스팅은 Python만의 특징 중 하나인 GIL(Global Interpreter Lock)의 개념에 대해 알아볼 것이다. Python 프로그래머라면 한 번쯤은 들어봤을 법한 용어지만, 정확하게 알고 있지 못한 분들도 많을 것

it-eldorado.tistory.com

 

반응형

'프로그래밍언어 > Python' 카테고리의 다른 글

[Python] Default Argument Value - mutable object  (2) 2023.12.02
[Python] Awaitable  (0) 2022.04.19
[Python] Decorator  (0) 2022.04.01
[Python] module, package, library  (0) 2022.02.11
[Python] copy  (0) 2022.02.08