TECH 으로 돌아가기
TECH HACKER NEWS 오늘 7분 읽기 25 READS

GIL 풀린 파이썬에서 NumPy는 얼마나 빨라질까 — free-threading 시대의 병렬 처리

파이썬의 30년 묵은 족쇄, GIL

파이썬으로 무거운 데이터 처리를 해본 분이라면 GIL이라는 단어에 한숨부터 나올 텐데요. GIL(Global Interpreter Lock)이 뭐냐면, 파이썬 인터프리터가 한 번에 딱 한 스레드만 파이썬 코드를 실행하도록 강제하는 잠금장치예요. 코어가 16개인 컴퓨터에서 스레드를 16개 만들어도, 파이썬 코드는 결국 한 줄씩 번갈아 실행되는 거죠. 그래서 파이썬에서 진짜 병렬 처리를 하려면 multiprocessing으로 프로세스를 여러 개 띄우는 우회로를 써야 했어요.

그런데 이 판이 지금 바뀌고 있어요. PEP 703이라는 제안이 통과되면서 GIL을 제거한 'free-threaded' 빌드가 파이썬 3.13에 실험적으로 들어왔고, 3.14부터는 공식 지원 단계로 올라왔거든요. 그리고 NumPy 핵심 기여자들이 소속된 Quansight Labs가 'free-threaded 파이썬에서 NumPy를 어떻게 확장하고 있는지'를 정리한 글을 공개했어요.

NumPy와 GIL의 애증 관계

사실 NumPy는 지금도 GIL과 나름 타협하며 살아왔어요. 큰 행렬 연산처럼 C 코드 내부에서 오래 도는 작업 중에는 GIL을 잠깐 풀어주기도 하거든요. 하지만 파이썬 레벨에서 스레드 여러 개로 NumPy 작업을 병렬로 돌리려고 하면, 각 스레드가 파이썬 코드를 실행할 때마다 GIL 쟁탈전이 벌어져서 성능이 안 나왔어요. free-threaded 빌드에서는 이 제약이 사라져요. 그냥 threading.Thread로 스레드를 만들면 정말로 여러 코어에서 동시에 돌아가는 거예요.

그런데 '그냥 되는' 게 아니에요

여기서부터가 진짜 어려운 부분인데요. 수십 년간 'GIL이 지켜준다'는 전제로 작성된 코드에서 그 전제를 빼면 온갖 문제가 튀어나와요.

첫째는 스레드 안전성이에요. NumPy 내부에는 전역 상태와 캐시가 곳곳에 있는데, 여러 스레드가 동시에 건드리면 데이터가 깨지거나 크래시가 나요. 이걸 하나하나 찾아서 잠금을 걸거나 구조를 바꿔야 해요.

둘째는 참조 카운팅 경합이에요. 파이썬은 객체마다 '몇 군데서 쓰고 있는지' 숫자를 세서 메모리를 관리하는데요, 여러 스레드가 같은 객체의 카운터를 동시에 올렸다 내렸다 하면 그 자체가 병목이 돼요. free-threaded 파이썬은 이를 완화하려고 만든 스레드가 주로 쓰는 객체는 싸게 처리하는 편향 참조 카운팅(biased reference counting) 같은 기법을 도입했어요.

셋째는 메모리 대역폭 한계예요. 이게 뭐냐면, 코어가 아무리 많아도 RAM에서 데이터를 실어 나르는 통로의 속도에는 한계가 있다는 거예요. NumPy 연산은 계산보다 데이터 이동이 많은 경우가 흔해서, 스레드를 늘려도 어느 순간부터는 대역폭이 꽉 차서 더 안 빨라져요. 스레드 8개면 8배가 될 거라는 기대는 현실에서는 조정이 필요한 거죠.

multiprocessing과 뭐가 다른데?

'어차피 multiprocessing으로 병렬 처리 되잖아' 하실 수 있는데, 결정적인 차이가 있어요. 프로세스는 메모리를 공유하지 않아서, 큰 배열을 넘기려면 직렬화(pickle)해서 복사해야 하거든요. 10GB짜리 배열이면 복사에만 한참 걸리고 메모리도 두 배로 먹어요. 스레드는 같은 메모리를 그대로 공유하니까 이 비용이 통째로 사라져요. 대용량 데이터 처리에서는 이게 게임 체인저가 될 수 있는 부분이에요.

생태계는 어디까지 왔나

3.13의 free-threaded 빌드는 단일 스레드 성능 손해가 꽤 컸는데, 3.14에서 많이 줄었어요. NumPy는 free-threaded용 배포판(휠)을 제공하기 시작했고, SciPy나 scikit-learn 같은 주변 라이브러리들도 대응 작업이 진행 중이에요. 관건은 C 확장 모듈들이에요. GIL을 전제로 짜인 서드파티 확장이 하나라도 안전하지 않으면 그 지점에서 문제가 생길 수 있거든요. 그래서 전환은 생태계 전체가 발맞춰 가는 장기전이 될 거예요.

우리는 뭘 해보면 좋을까

데이터 파이프라인, 이미지 처리, 수치 시뮬레이션을 파이썬으로 하는 분들이라면 지금부터 지켜볼 가치가 충분해요. 프로덕션에 바로 넣기는 이르지만, free-threaded 빌드(보통 python3.14t처럼 t가 붙어요)를 설치해서 자기 워크로드가 스레드로 얼마나 빨라지는지 실험해보는 건 지금도 할 수 있거든요. 쓰는 라이브러리가 free-threaded 휠을 제공하는지 확인하는 것도 포인트고요.

정리하면, '파이썬은 멀티코어를 못 쓴다'는 오래된 상식이 무너지는 중이고, NumPy가 그 최전선에서 기반을 다지고 있다는 얘기예요. 여러분의 워크로드 중에 multiprocessing의 복사 비용 때문에 포기했던 병렬화, 혹시 있으신가요? free-threading이 성숙하면 뭐부터 바꿔보고 싶으세요?


🔗 출처: Hacker News

SOURCE · HACKER NEWS
원문 전체 보기 → https://labs.quansight.org/blog/scaling-numpy-on-free-thread...
SHARE
처리 중...