[혼자 공부하는 파이썬]에서 생성자를 배울 때 소멸자를 배웠고,
소멸자를 배울 때 언제 소멸하는지를 알기 위해 가비지 컬렉터 개념을 배웠으며
가비지 컬렉터를 사용하는 GIL에 대해 알게 되어서
GIL이 운영체제를 공부한 부분과 밀접한 관련이 있길래 파이썬의 동시성 관리에 대해 학습했다.
가비지 컬렉터
가비지 컬렉터: 메모리를 효율적으로 사용하기 위해 사용되지 않는 객체를 메모리에서 해제하는 메모리 관리 메커니즘.
'사용되지 않는 객체' 판단 기준- [혼자 공부하는 파이썬]에선 변수에 저장되지 않거나, 함수에서 나오는 케이스를 예시로 듦.
참조 카운팅: 객체가 몇 번 참조되었는 지를 추적하고, 카운트가 0이면 사용되지 않는 것으로 판단
import sys // sys.getrefcount(객체)
(sys.getrefcount함수에서 매개변수로 받을 때도 참조되므로 참조된 수가 1 늘어난다.)
gc 모듈 사용: 가비지 컬렉터 제어 모듈
gc.isenabled() gc.disable() gc.enable()
gc.collect() #가비지 컬렉터 강제 실행
Cpython
파이썬은 인터프리터 언어(코드를 한 줄씩 읽으면서 실행)이며 동적 프로그래밍 언어이기 때문에
변수의 형 타입을 동적으로 변형하고 확인해야 하는 측면에서 속도 저하를 발생시킨다.
Cpython은 이러한 단점을 보완한 구현체로, C로 작성한 파이썬 인터프리터이다.인터프리터를 실행할 때 C로 작성된 내부 함수로 변환하여 실행함.파이썬 소스코드 -> Cpython -> 바이트코드로 컴파일 (.pyc 확장자) -> 바이트코드 실행
C로 작성된 확장 모듈을 지원하기 때문에 파이썬 코드를 C언어로 작성된 여러 라이브러리와 통합 가능
GIL을 사용하여 메모리 관리 및 스레드 안전성을 확보한다.
GIL (Global Interpreter Lock)이란?
GIL: 한 시점에 하나의 스레드만 파이썬 인터프리터를 제어를 유지할 수 있도록 하는 뮤텍스(lock)
(멀티 쓰레싱 자체는 가능하지만 여러 스레드의 병렬 실행은 불가능 -> 다중 스레드 코드에서 병목 현상 발생)
인터프리터가 한 번에 하나의 스레드만 실행할 수 있게 하고 스레드 스위칭을 통해 멀티 쓰레싱을 가능케 한다.
장점
파이썬은 참조 카운팅을 사용하여 메모리를 관리하는데,
카운트 변수가 동시에 접근되는 상황에서 보호가 필요하기 때문에 GIL을 사용한다.
(GIL을 사용하지 않으면 모든 객체에 뮤텍스를 걸어줘야하는 비효율적인 상황이 발생)
CPU 연산의 비중이 적은 I/O 바인딩된 프로그램은 외부연산이 많기 때문에 입출력을 기다리면서
낭비하는 시간을 멀티 쓰레싱을 통해 절약할 수 있다.
(GIL은 참조 카운팅에 대한 race condition 문제를 방지하기 위함이므로
외부 연산에 대해선 GIL이 해제되어 다른 스레드로 넘어감)
단점
CPU 집약적인 작업에서 병목 현상 및 잦은 문맥 전환으로 인한 멀티 쓰레싱의 성능 저하의 단점이 있다.
필요성
GIL의 단점에도 불구하고 C의 확장 기능을 사용하고,
싱글 스레드 성능을 저하시킬 수 있기 때문에 GIL을 계속해서 사용한다.
GIL 우회 방법
멀티프로세싱: multiprocessing 모듈을 사용하여 병렬 처리를 수행한다.
각 프로세스는 서로 다른 독자적인 메모리 공간을 가져서 공유 자원 race condition으로부터 자유롭기 때문이다.
다만 멀티프로세싱에서의 문맥 전환이 멀티스레싱에서의 문맥전환보다 더 많은 비용이 들기 때문에
CPU 바인딩 작업에서만 사용하는 것이 좋다.
'Lauguage > Python' 카테고리의 다른 글
[Python] 캡슐화 (0) | 2024.06.15 |
---|---|
[Python] 동시성 관리 (1) | 2024.06.15 |
[Python] [혼자 공부하는 파이썬] Chapter 8. 클래스 (0) | 2024.06.10 |
[Python] [혼자 공부하는 파이썬] Chapter 6-7 예외처리, 모듈 (1) | 2024.06.08 |
[Python] [혼자 공부하는 파이썬] Chapter 5. 함수 (1) | 2024.06.06 |