Wireframe

파이썬 3.12에서 GIL 없는 병렬처리 도입 계획

최근 발표된 파이썬 3.11은 이전 버전 대비 10~60% 이상의 성능 향상을 보여 화제가 되었습니다. 뭐 파이썬이 원래 느려 먹어서 그정도는 쉽게 되는 거 아니냐는 사람들도 있는데, 파이썬3는 이미 파이썬 3.8부터 파이썬2보다 빠르다고 평가를 받아왔고, 계속해서 10% 가량의 성능을 개선해오다가 3.11에서 향상 폭이 커진 것입니다. 표준 파이썬 구현체의 비약적인 성능 개선을 위해 Faster CPypthon이라는 별도의 프로젝트가 기획되었고, 3.10부터 결과물이 나오고 있는 것입니다.

이 프로젝트의 3.12 버전에 대한 이 프로젝트의 목표 중 하나에 관심이 가는데, 그것은 진정한 멀티 스레드 병렬작업을 가능하게 하겠다는 것입니다. 현재까지 파이썬은 “전역 인터프리터 락”이라는 것을 사용하여 프로세스 내의 여러 스레드들이 실제로는 동시에 돌아가지 않고 각 스레드들이 번갈아가며 “한 번에 하나씩만” 실행되는 형태로 작동합니다. 그래서 스레드를 사용해서 동시에 작업을 실행하더라도, 한쪽 작업이 I/O 등 CPU를 사용하지 않는 일을 하지 않는 이상 실행 시간이 단축되지 않습니다.

그래서 프로세스내 전역 상태를 스레드 안전하게 만들고, 프로세스 내에서 여러 개의 서브 인터프리터가 동시에 실행되는 형태로 실제로 동시에 여러 코드가 실행되는 형태로 구현하겠다는 아이디어가 채택되었습니다. (PEP 684) 그리고 이 서브 인터프리터를 파이썬 프로세스 내에서 생성할 수 있게 하여(PEP 554) 이것으로 다중 스레드를 대체하는 것입니다.

실제로 ‘멀티 인터프리터’ 개념은 파이썬 초기(1.5)부터 존재했었습니다. 그러나 한 프로세스 내의 각각의 인터프린터들은 너무 많은 전역 상태를 공유했기 때문에, 동시에 작동할 때 발생하는 문제가 많았죠. 전통적인 동기화 수단들을 사용하여 GIL을 없애보려는 시도도 있었으나 전체적인 성능이 너무 저하되거나, 코드를 유지보수하기가 너무 까다로워지는 등의 이유로 중단되거나 했습니다. PEP684는 각각의 인터프리터를 “충분히” 격리하고 GIL을 각각의 인터프리터 내부로 옮기는 것에 관한 내용입니다. 그렇게 하면 하나의 인터프리터는 여전히 GIL의 영향을 받지만, 서로 다른 인터프리터는 영향을 받지 않으면서 실제로 동시에 CPU를 점유하여도 문제가 생기지 않게 하겠다는 것이죠.

PEP 554는 멀티인터프리터 혹은 서브인터프리터를 프로세스에서 직접 생성하고 사용하는 인터페이스를 만드는 것입니다. interpreters 라는 새로운 모듈이 추가되고 이 모듈에서 서브 인터프리터 관련한 기능을 제공합니다. 그리고 각각의 인터프리터는 채널이라는 수단을 통해서 마치 스레드 간에 큐를 사용하여 데이터 교환을 하는 것과 비슷한 방식으로 데이터를 교환합니다. PEP 554에서는 None, int, str, bytes 와 같은 단순한 타입에 대해서 우선적으로 지원하고 이후 교환 가능한 데이터 타입을 확대하겠다는 계획입니다.

import interpreters
import textwrap as tw
from threaing import Thread

interp = interpreters.create()
recv, send = interpreters.create_channel()

def run():
  interp.run(tw.dedent("""
    reader.recv()
    print("during")
    """),
    shared=dict(reader=r,))
  )

t = threading.Thread(target=run)
print('before')
t.start()
print('after')
s.send(b'')

커뮤니티 내에서도 GIL을 서브인터프리터로 옮기는 것에 대해서 많은 논의가 있는 것 같습니다. GIL을 서브인터프리터 내부로 넣는 것은 소잡는데 엑셀 팡션 쓰는 것 아니냐, 아직 표준라이브러리에 넣기에는 시기상조 아니냐, 하위 호환성은 어떡하냐 등등..

개인적으로는 어찌됐든 시기의 문제라고는 생각합니다. CPU의 코어 하나의 성능이 무한정 빨라질 수 없는 것은 자명하고, 컴퓨터 산업 자체가 멀티코어 기반으로 성능을 뽑아내는 쪽으로 발전해가고 다른 언어들도 그러한 방향을 지향하고 있는데 파이썬만 끝까지 “아 우리는 GIL.. 데헷 🙂 ” 이러고만은 있을 수 없으니까요. 물론 서브 인터프리터가 3.12에 실제로 포함될지는 모르는 일입니다. 이 내용은 아직까지 이 팀의 ‘목표’이니까요. 그리고 다른 목표들도 아직 갈길이 멀어 보입니다.

어쨌든 이런 논의가 그저 논의에만 그치지 않고 액션으로 착수됐다는 점은 상당히 고무적입니다. 그리고 3.12의 계획을 보면 어쩌면 3.11에서 보여준 드라마틱한 향상의 수준에 버금가거나 그 보다 더 큰 효과를 기대해도 좋지 않을까 하는 부분들이 있어서, 3.12의 진행도 관심을 가지고 지켜봐야겠습니다.

Exit mobile version