-
Python GIL개발 2025. 12. 28. 17:53
CPython
파이선 스크립트 엔진중에 가장 메인. 공식 배포판에서도 이걸 쓴다.
- C 언어로 작성되었고 공식 배포판이다
- 가장 완벽하고 모든 최신 기능을 제공한다
- 커뮤니티가 가장 크고 풍부한 문서를 제공한다
터미널에서 python 명령어를 실행하면 CPython 엔진으로 파이선 파일을 실행하게 된다
GIL
글로벌 인터프리터 락 (Global Interpreter Lock). 쓰레드간에 동시성을 제어하기 위해 사용되는 메커니즘. GIL 은 동시에 하나의 쓰레드만 바이트코드를 실행할 수 있도록 허용하며 메모리 관리와 객체 모델의 일관성을 보장한다
왜 파이썬은 하나의 스레드만 바이트 코드를 실행하게 했는지 궁금할 수 있는데 자세히 들어가면 복잡하니 C 언어 생태계에서 단일스레드 성능을 높이기 위함이였다 정도로 짧게 이해하고가자
동작방식
락의 획득과 해제: CPython 인터프리터가 파이선 코드 실행시 GIL 을 획득하고 다른 쓰레드는 GIL 을 실행할 때까지 대기. 인터프리터는 주기적으로 GIL 을 해제하여 다른 쓰레드가 실행될 수 있도록 한다
스레드 전환: GIL 은 바이트코드 실행 주기 또는 I/O 작업이 발생할 때마다 다른 쓰레드로 전환된다. 단일 코어에서 다중 쓰레드가 실행되는것처럼 보이지만 실제로는 하나의 쓰레드만 실행된다
장점
메모리 관리 간소화: 쓰레드가 동시에 메모리 객체에 접근해도 GIL 은 일관성을 유지할 수 있게 해준다
안전성: GIL 덕분에 파이썬 내부 데이터 구조가 쓰레드 안정성을 유지한다
단점
멀티코어 CPU 활용 제한: 파이썬 쓰레드는 동시에 하나의 쓰레드만 실행되므로 병렬처리가 제한된다. CPU 바운드 작업에서 성능 저하를 초래한다
쓰레드 성능 저하: I/O 바운드 작업에서는 큰 문제가 안되지만 CPU 바운드 작업에선 멀티쓰레딩의 이점을 누리지 못함
다음코드가 GIL 병목의 대표적인 예제 코드다
import threading def work(): x = 0 for _ in range(10**8): x += 1 threads = [threading.Thread(target=work) for _ in range(4)] for t in threads: t.start() for t in threads: t.join()x+=1 단순한 코드를 돌리는데 멀티 스레드 환경이지만 한번에 하나의 스레드만 실행이 가능하다. 실질적으로 하나의 스레드로 돌리는 것과 비슷한 속도가 발생
CPU 바운드 작업이 높은 서비스의 경우에는 c++ 을 이용한 내장 라이브러리를 적극 활용해야 GIL 병목에 걸리지 않는다 -> 암호 해체 관련된 작업의 경우 락에서 보내는 시간이 많아질수도
반면에 I/O 관련 작업이 많다면 GIL에서 걸리는 시간이 많지 않다.
Django
장고도 CPython 으로 실행하면 GIL 때문에 쓰레드 동시성 문제를 겪게됨. 그래서 wsgi 를 이용해 worker 프로세스를 여러개 둬서 멀티 프로세싱을 사용한다.
멀티 쓰레드도 두긴 하는데 이건 I/O 바운드 작업을 최적화 하기 위함임
'개발' 카테고리의 다른 글
[Kube] Node, Node Pool, Taint, Label (1) 2024.11.27 [Python] Decorator (0) 2024.05.17 [파이썬] 파이썬은 모든것이 객체다 (0) 2024.05.09 [python] __all__ 을 이용해 전체 임포트 막기 (0) 2024.05.08 __init__.py 를 이용한 모듈 관리 (0) 2024.05.08