[AI] 단일 스레드 환경인 파이썬에서, 왜 스레드 수 제한이 유효했을까? - 100-hours-a-week/5-yeosa-wiki GitHub Wiki
1. 이 생각이 들게 된 계기
-
기본적으로 Python은 GIL로 인해 단일 스레드 환경으로 작동하는 것으로 알고 있었음.
-
그런데 모델 학습 중
torch.set_num_threads
를 설정했더니,실제로 CPU 사용률이 줄어드는 현상을 관찰함.
-
만약 Python이 진짜 단일 스레드로만 동작했다면 스레드 수 설정이 의미가 없었을 것.
-
그래서 "PyTorch는 내부적으로 다중 스레드로 동작하고 있는 것 아닐까?"라는 의문이 생김.
2. GIL (Global Interpreter Lock)이란?
-
GIL은 CPython 인터프리터 내부에 존재하는 락.
-
한 순간에 하나의 스레드만 Python 바이트코드를 실행할 수 있도록 강제.
-
이로 인해 Python은 멀티스레드 환경에서도 CPU 바운드 작업에서 진정한 병렬성 확보가 어려움.
-
GIL이 네트워크 바운드와 CPU 바운드에 미치는 차이
- 네트워크 바운드 작업: I/O 대기 중 다른 스레드로 전환이 가능.
- CPU 바운드 작업: 한 스레드가 CPU를 독점하여 GIL이 병목이 됨.
구분 네트워크 바운드 작업 CPU 바운드 작업 CPU 사용 거의 없음 (대기 상태) 지속적인 사용 스레드 전환 대기 중 자연스럽게 전환 전환 어려움 (GIL 독점) 멀티스레딩 효과 큼 적음 예시 웹 요청, 파일 다운로드 수치 계산, 데이터 암호화
3. PyTorch는 어떻게 작동하는가?
-
PyTorch는 Python에서 명령만 전달하고, 실제 연산은 **C++ 네이티브 코드(ATen, THC 등)**가 수행.
-
Python 레벨에서는 CPython GIL이 적용되지만, C++ 연산 중에는 GIL이 해제됨.
-
C++ 코드 실행 동안에는 Python 인터프리터 제약 없이 멀티코어 병렬 연산이 가능.
-
따라서
torch.set_num_threads
를 설정하면 내부 C++ 스레드 수를 제어할 수 있고, CPU 사용량에도 직접적인 영향을 준다. -
흐름 요약
Python 코드 ↓ (명령 전달) PyTorch Python Bindings ↓ (C++ 함수 호출) ATen, TH 라이브러리 (C++ 연산 엔진) ↓ CPU/GPU에서 실제 연산 ↓ Python 오브젝트로 결과 반환
4. torch.set_num_threads가 CPU 사용량을 줄이는 이유
torch.set_num_threads(n)
은 PyTorch 내부 C++ 연산 시 사용할 스레드 수를 설정.- 내부적으로 OpenMP, pthreads 같은 라이브러리를 통해 병렬 연산을 수행.
- 스레드 수를 줄이면 병렬 처리 양이 줄어들고, 결과적으로 CPU 사용량도 감소.
5. 최종 요약
- GIL은 Python 코드 실행을 한 번에 하나의 스레드로 제한.
- PyTorch는 Python을 통해 명령을 전달하지만, 실제 연산은 GIL이 해제된 C++ 코드가 수행.
- C++ 코드에서는 멀티스레드, 멀티코어 병렬 처리가 가능.
torch.set_num_threads
를 통해 내부 병렬 스레드 수를 제어할 수 있으며, 이로써 CPU 사용량을 효과적으로 관리할 수 있다.