ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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 바운드 작업을 최적화 하기 위함임

     

     

    댓글

Designed by Tistory.