Free Threaded 파이썬의 첫 1년 돌아보기
(labs.quansight.org)- 프리 스레드 파이썬은 멀티코어 하드웨어를 효율적으로 활용할 수 있도록 설계됨
- CPython 3.14에서는 핵심 모듈의 스레드 안전성과 성능이 대폭 개선됨
- 아직 프리 스레드 빌드를 지원하지 않는 많은 주요 패키지들이 남아있음
- 누구든 실사용 환경에서의 보고와 커뮤니티 기여를 통해 발전에 함께할 수 있음
개요
지난주 CPython 3.14.0b1이 공개되었고, 이번 주에는 PyCon 2025가 피츠버그에서 시작됨
이 두 가지 이벤트는 프리 스레드 파이썬의 배포와 안정화 측면에서 중요한 이정표임
이 글은 지난 1년간의 과정을 돌아보고, Quansight 팀이 복잡한 의존성을 가진 실제 프로덕션 워크플로우에 프리 스레드 빌드를 실험적으로 적용하는 데 어떻게 핵심 역할을 했는지 설명함
프리 스레드 파이썬의 의미와 필요성
- 프리 스레드 파이썬 지원은 멀티코어 CPU와 GPU가 보편화된 현대 하드웨어의 전체 연산 자원 활용을 가능하게 함
- 기존 GIL(글로벌 인터프리터 락) 방식에서는 병렬 알고리듬을 완전히 활용하려면 우회 방법과 별도의 튜닝이 필요했음
- 보통 threading 모듈보다는 multiprocessing을 사용했으나, 이것은 프로세스 생성 비용이 크고, 데이터 복사도 비효율적임
- 파이썬 패키지 중 네이티브 코드를 포함하는 경우, 프리 스레드 빌드가 바로 호환되지 않으므로 스레드 안전성 보장을 위해 코드 감사를 반드시 수행해야 함
- GIL 해제는 CPython 인터프리터에 깊은 구조적 변화를 필요로 했고, 기존 패키지의 구조적 문제까지 드러내는 계기가 되었음
주요 성과
-
Meta의 Python 런타임 팀과 함께, 아래와 같은 다양한 패키지와 프로젝트에 프리 스레드 Python 지원을 기여함
- meson, meson-python, setup-python GitHub Actions, packaging, pip, setuptools 등 패키징 및 워크플로우 도구
- Cython, pybind11, f2py, PyO3 등 바인딩 생성기
- NumPy, SciPy, PyArrow, Matplotlib, pandas, scikit-learn, scikit-image 등 PyData 생태계의 핵심 패키지
- Pillow, PyYAML, yarl, multidict, frozenlist 등 PyPI 다운로드 상위 주요 의존성
- 아직 지원하지 않는 인기 패키지들(CFFI, cryptography, PyNaCl, aiohttp, SQLAlchemy, grpcio 등)과 머신러닝 라이브러리(safetensors, tokenizers 등)도 점진적으로 작업 중임
- Quansight 팀의 CPython 핵심 개발자들은 3.14 버전에 다음과 같은 개선 사항을 반영함
- warnings 모듈이 프리 스레드 빌드에서 기본적으로 스레드 안전하게 동작함
- asyncio의 심각한 스레드 안전성 문제 개선 및 병렬 확장성 증가
- ctypes 모듈에서 스레드 안전성 전면 개선
- 프리 스레드 가비지 컬렉터 성능 향상
- deferred reference counting 스킴 및 적응형 특수화 인터프리터 최적화
- 수많은 버그 수정과 스레드 안전성 보완 진행
- 프리 스레드 Python 지원을 위한 종합적 가이드1도 작성하여, 앞으로 더 많은 패키지에 실질적으로 참고될 수 있는 문서화를 제공함
프리 스레드 파이썬 생태계 현황
- 1년 전(3.13.0b1 출시 당시에) 프리 스레드 빌드에서 대부분의 파이썬 패키지 설치가 전면적으로 깨지는 상황이었음
- 빌드 실패 원인은 근본적인 문제라기보다, 지원되지 않는 기본 옵션이나 작은 가정이 깨졌기 때문임
- 지난 1년간 커뮤니티와 협력하여 많은 문제를 해결했고, 특히 Cython 3.1.0이 공식 지원되면서 큰 전환점이 됨
- 아직도 컴파일된 코드를 포함하지만 프리 스레드 휠을 제공하지 않는 패키지들이 남아 있음
이들의 진행 상황은 수동 및 자동 추적 테이블2에서 확인 가능함
당면 과제
- 현재 프리 스레드 파이썬 빌드는 실제 워크플로우에서의 실험과 피드백이 필요한 단계임
- 멀티프로세싱 사용 비용이 큰 워크플로우 등에서 특히 성능 개선 가능성이 있지만, 각 패키지에 대한 세밀한 스레드 안정성 감사가 필수적임
- 많은 라이브러리들이 뮤터블 자료구조를 제공하면서 스레드 안전성 문서화나 실제 안전 보장이 미흡함
- 패키지 규모가 크고 레거시가 많은 경우, 코드를 완전하게 파악할 수 있는 사람이 부족해 지원이 늦어지는 현상 발생
- 커뮤니티 차원에서 핵심 패키지 유지관리의 지속 가능성을 위한 노력이 필요함
기여 방법
- 공식 가이드의 기여 안내서를 참조할 수 있음
- 전체 생태계 이슈를 추적하고, 주요 호환성 문서는 free-threaded-compatibility 저장소5에서 관리함
- Quansight-Labs 주관 커뮤니티 Discord6에서 토론 참여 및 기여 가능함
PyCon 발표 예정 안내
- 본문 저자와 팀원인 Lysandros Nikolaou가 PyCon 2025에서 발표할 예정임
- 경험에서 비롯된 실질적인 포팅 사례와 노하우를 공유할 계획이며, YouTube 녹화 영상도 제공 예정임
- 프리 스레드 빌드는 파이썬 언어의 미래라 믿으며, 이를 실현하는 데 기여할 수 있음에 큰 기대감을 가짐
- 오늘의 노력이 매일 수백만 개발자가 사용하는 다양하고 방대한 패키지의 미래를 여는 전환점이 되길 희망함
Hacker News 의견
-
많은 사람들이 멀티프로세싱을 사용하는데, 프로세스 생성 비용이 비싸다는 점 언급
-
SharedMemory 기능이 존재하는데, 왜 더 자주 사용되지 않는지 이해 못함
-
ShareableList 사용 경험이 좋았다는 점 강조
-
유닉스에서 프로세스 생성 속도는 1ms 미만 수준
- 하지만 PYTHON 인터프리터 프로세스 시작은 import 개수에 따라 30ms~300ms 걸릴 수 있음
- 1~2자리수의 차이가 있으므로 정확한 수치 중요
- CGI는 이 점에서 예외이며, C·Rust·Go로는 문제 없음
- sqlite.org도 요청당 개별 프로세스 방식 사용 중이라는 예시 공유
-
ShareableList는 원자 스칼라와 bytes·문자열만 공유 가능
- 파이썬의 구조화된 객체는 pickle dump 등 직렬화 비용 및 프로세스별 복제 메모리 비용 발생
-
numpy 배열 공유에서 큰 성공 경험
- 명시적 공유 방식은, 스레드 간 실수로 공유해서 발생하는 문제 디버깅 난이도에 비하면 부담 아님
- 많은 사람들이 스레드가 멀티프로세싱에 비해 얼마나 좋은지 과대평가함
- GIL이 해제되면 난수성 segfault 디버깅이 늘어날까봐 걱정
- JavaScript가 공유 메모리 기반 스레딩을 지원하지 않는 것에 사람들이 크게 불평하지 않은 점 언급
- JavaScript는 속도가 빨라서 그런 필요가 적다는 해석
- 파이썬의 기본 성능 개선에 더 많은 노력이 필요하다는 바람
-
프로세스가 독립적으로 죽기 때문에, 락 잡은 채로 공유 메모리 데이터 구조를 수정중이던 프로세스가 죽으면 복구 어렵다는 점
- Postgres의 공유 메모리 구조와 전체 백엔드 프로세스 종료 필요 예시
- 스레드는 함께 죽는 구조라서 이런 문제 발생 인식이 덜 하다는 점
-
공유 메모리는 전용 하드웨어에서만 동작
- AWS Fargate 같은 환경에서는 공유 메모리 없음, 네트워크 또는 파일시스템 사용 필요로 인해 레이턴시 증가
- fork 방식의 프로세스 복제는 또 다른 문제
- 실제 경험상 green thread와 actor 모델이 훨씬 더 효과적이었다는 주장
-
-
GIL 제거가 파이썬 멀티스레드 코드에 병렬 처리 외에 다른 영향이 있는지 궁금함
-
GIL이 유지된 이유는 멀티스레드가 GIL에 의존해서가 아니라, GIL 제거가 인터프리터 구현과 C 확장, 단일 스레드 코드 속도 저하를 유발하기 때문이라는 이해
-
Free-threaded Python이 bytecode 경계에서 언제든 선점될 수 있다는 기존 보장과 동일한지 궁금
-
아니면 락을 더 써야 하는 등 작성 방식이 달라지는지 궁금
-
free-threaded Python도 대부분 같은 보장
- 다만, free-threading이 없으면 사람들이 스레딩 기능을 덜 쓰고, 경계에서 선점되는 버그가 실제로 잘 발생 안함
- free-threading 도입 시 더 많은 버그 노출
- 멀티프로세스 우회 방법을 쓸 필요가 없어져 유저 코드가 간단해짐; 인터프리터 복잡성 증가의 가치가 충분하다고 생각
- C 확장 복잡화 문제는 free-threading보다 sub-interpreter가 더 심함; numpy팀이 sub-interpreter는 지원 못한다고 명확히 밝힘
- numpy는 이미 free-threading 지원, 남은 버그 수정 중
- 단일 스레드 속도 약간(한자리수 %) 느려지는 건 감수할 만한 트레이드 오프
-
멀티코어 사용은 가능하나, 스레드당 성능 저하와 라이브러리 재작업 필요
- PyTorch로 실험 시, 10배 CPU 사용에 절반의 작업 처리량 경험
- 시간이 지나며 개선 기대, 20년 간 이걸 기다려온 만큼 반가움
-
경쟁상황(레이스 컨디션)이 더 빈번하게 발생할 수 있으니, 신뢰도 보장을 위해 멀티스레드 파이썬 작성에 더 많은 주의 필요
-
-
Microsoft가 Faster Python 팀을 해산했다는 소식 전달
-
2025 예상 실적 미달로 팀 유지 안됐던 것
-
향후 CPython에 성능 개선이 추가되는지, 혹은 타사가 후원하는지 지켜볼 예정
-
Facebook(메타)는 아직 일부 후원 중인 것으로 보임
-
Microsoft의 약속 대비 일정이 크게 지연되었던 점 언급
- 최근에는 심각한 정치·거버넌스 문제를 알고 있을 것; 유능한 직원이 괜히 기여해 그룹 비방을 당하고 싶지 않을 것이라는 의견
- CPython 조직이 약속 과다, 순응파에 일거리를 몰아주고 유능한 반대자를 내몬다는 비판
- 과거에는 이런 문제가 없었음, 현재 스스로 야기한 문제
-
이런 결과는 아쉽지만, Microsoft의 장기 약속을 신뢰하지 않았던 본인의 예상이 맞았다는 언급
-
최근 Google도 전체 파이썬 개발팀을 해고한 것 같다는 소문
- 둘 다 시대적 원인이나 공통 분모가 있는지 궁금
-
매우 안타깝지만, embrace & extend 이후 남은 건 하나뿐이라는 뉘앙스
-
-
파이썬에서 GIL이 사라지는 걸 걱정하는 사람이 자신뿐인지 궁금
-
어떤 언어든 복잡한 멀티스레드 코드는 신뢰 어렵고, 파이썬은 동적 특성상 특히 더 불안
-
혼자만 변화에 대한 두려움이 있는 게 아니며, 근거가 비합리적일 수 있다는 점
- GIL이 순수한 기술부채이니, 커뮤니티 이익을 위해 제거 필요
- 요즘 파이썬에서 대부분 스레드 대신 non blocking IO와 async 사용
- 스레드 사용 안하면 GIL 제거로 인한 변화 없음; C 라이브러리도 단일 스레드로 안전
- 스레드 실제로 사용하면만 주의 필요
- 나이브한 스레드 파이썬 코드는 지금까지 GIL에 막혀 단일 스레드처럼 동작했는데, 이제는 좀 빨라지되, 버그가 늘어날 수도 있음
- 해결책은 스레드를 안 쓰거나, 쓰려면 제대로 배우면 된다는 조언
- 앞으로 더 좋은 추상화 제공될 테니, 커뮤니티에서 structured concurrency 등 논의 기대
-
본인은 asyncio를 적극 사용하고 있음
- 싱글 스레드이지만 concurrent한 파이썬을 즐겁게 작성 가능; Node.js처럼 사용
- 웹·네트워크 작업에는 이런 방식 추천
-
ML/AI 분야에서처럼 전문가가 복잡 라이브러리를 먼저 만들고, 일반 사용자에겐 그것을 전달하는 구조 예상
- 파이썬의 GIL이 심각한 병목이 되는 경우들이 많아졌음
- 그래서 Go 언어를 배움; 스레드 지원 제대로 되는, 파이썬보다 하위, C/C++보다는 상위 추상화라 할 수 있음
- 컴파일러 방식도 스레딩 못지 않게 중요한 배경
-
괜한 불안 조장이 될 수도 있지만, LLM이 지난 수십 년간의 GIL 존재 가정 하의 파이썬 코드로 학습된 사실 상기
-
GIL 유무는 멀티코어 작업을 원하는 사람에게만 해당
- 현재도 스레딩·멀티프로세싱에 신경 쓰지 않았다면 실질적 변화 없음
- 레이스 컨디션 이슈는 GIL 유무와 상관 없이 발생
-
-
파이썬을 자주 사용하지만 전문가 아니며, 가끔 concurrent.futures로 단순 함수 여러 개 동시 실행
-
이런 사용자가 앞으로 무엇을 바꿔야 하는지 궁금
-
스레드가 GIL에 묶이지 않아 전체적으로 더 빨라짐
- 공유 객체 락만 제대로 처리했다면 추가 걱정 불필요
-
-
20년간 파이썬으로 프로 개발 경험에서 느끼는 점 공유
-
스레드가 진짜로 필요할 때는 메시지 패스가 불가피한 경우에 한정
- 파이썬 생태계가 이미 이런 모든 상황의 우회책 제공
- 여러 스레드 핸들링 함정(락 등) 때문에, 앞으로 특정 라이브러리·도메인에서만 필요할 수 있음
- 순수 파이썬만으로 최대한 성능 뽑아내려면 native code 기반 라이브러리(ex. Pypy, numba) 활용 가능
- 파이썬의 성능 혁신은 결국 async 프로그래밍; 꼭 배워보길 추천
-
파이썬을 비슷하게 오래 썼고 동의하지만, 약간 다르게 표현
- 파이썬 스레드가 워낙 별로라서, 피하기 위한 다양한 우회책이 발전
- CPU-bound 작업을 스레드로 2배 빨리하려다 GIL 문제에 부딪혀, 멀티프로세싱으로 전환; 데이터 구조 직렬화로 인한 비용 발생, 2배 코어에 1.5배 속도 등 비효율적 경험
- 좋은 스레드 지원이 생기면 활용하고 싶은 환경 많음; 여태 없으니 각종 대체 접근법을 썼다는 점
- 상황에 맞으면 async 활용 강력 추천(글리프, 당신 말이 맞았어요!)
-
-
AI 이미지이지만, 뱀에 꼬리가 두 개 그려진 것 의아함
-
조용히 넘어가라는 찬조 의견; 파이썬 기사에 뱀 그림 들어가면, 대체로 딱히 신경 쓸 가치 없는 신호라고 유희적으로 언급
-
'Confusoborus'라는 농담식 명칭 제안
-
-
헤더 이미지의 뱀이 두 개의 꼬리를 가진 듯하다는 지적
- 같은 프로세스 내에서 두 번째 스레드를 생성한 모양이라는 익살
-
라이브러리 지원 외에, WSGI와 Celery 워커를 단일 프로세스로 띄우는 것에 다른 제약이 있는지 궁금
- 제약은 없으나, 이런 방식이 언어의 1급 기능이 아니라는 점
- GIL은 기술부채 이슈라는 설명
- 병렬성 외에도 GIL 해제가 필요한 요소 존재
- 제약은 없으나, 이런 방식이 언어의 1급 기능이 아니라는 점
-
앞으로의 성능 시대를 위한 엄청난 기반 작업이라고 생각