PyPy가 CPython 보다 빠른 이유

Updated:

PyPy

PyPy는 유연함과 쉬운 실험을 위해 파이썬 프로그래밍 언어 자체로 작성된 파이썬 구현체이다. 이 프로젝트의 목적 중 하나는 최적화된 PyPy의 파이썬 구현이 현재의 C 구현보다 빠르도록 하는 것이다. PyPy 자체는 파이썬 언어의 부분집합인 RPython으로 구현되어 있다.

PyPy는 파이썬 코드를 기계어나 다른 저급 언어로 자동 번역하는 저스트 인 타임 컴파일러 기능을 포함하고 있는데, 특이한 점은 JIT 컴파일러 자체가 JIT 컴파일러 생성기로부터 — PyPy RPython 코드를 분석하여 — 자동생성된다는 점이다.

벤치마크 대상에 따라 다르긴 하지만 PyPy 1.4 버전부터 CPython보다 나은 성능을 보인다.

image

CPython

CPython 은 Python 프로그래밍 언어 의 참조 구현 입니다 . C 와 Python으로 작성된 CPython은 기본적으로 가장 널리 사용되는 언어 구현입니다.

CPython의 특정 기능은 각 CPython 인터프리터 프로세스 에서 GIL ( Global Interpreter Lock ) 을 사용한다는 것입니다. 즉, 단일 프로세스 내에서 한 번에 하나의 스레드 만 Python 바이트 코드를 처리 할 수 있습니다. 이것은 멀티 스레딩에 아무런 의미가 없다는 것을 의미하지는 않습니다. 가장 일반적인 멀티 스레딩 시나리오는 스레드가 대부분 외부 프로세스가 완료되기를 기다리는 경우입니다.

PyPy vs CPython

간단히 말하면 CPython 은 일반적인 인터프리터인데 반해 PyPy 는 실행 추적 JIT(Just In Time) 컴파일을 제공하는 인터프리터기 때문이다. PyPy 는 RPython 으로 컴파일된 인터프리터인데, C 로 작성된 RPython 툴체인으로 인터프리터 소스에 JIT 컴파일을 위한 힌트를 추가해 CPython 보다 빠른 실행 속도를 가질 수 있게 되었다.

실제로 PyPy가 하는 일은 크게 두 가지이다.

  1. RPython 언어로 동적 언어의 인터프리터를 구현할 수 있게 해주는 프레임워크
  2. RPython으로 구현된 Python

JIT (Just-In-Time)

동적 번역(dynamic translation)은 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일 기법이다. 이 기법은 프로그램의 실행 속도를 빠르게 하기 위해 사용된다.

인터프리터 방식과 비교

인터프리터

바이트코드 명령어를 하나씩 읽어서 해석하고 실행한다. 하나씩 해석하고 실행하기 때문에 바이트코드 하나하나의 해석은 빠른 대신 인터프리팅 결과의 실행은 느리다는 단점을 가지고 있다.

흔히 얘기하는 인터프리터 언어의 단점을 그대로 가지는 것이다. 즉, 바이트코드라는 ‘언어’는 기본적으로 인터프리터 방식으로 동작한다. (python 과 동치)

JIT(Just-In-Time) 컴파일러

인터프리터의 단점을 보완하기 위해 도입된 것이 JIT 컴파일러이다. 인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여 네이티브 코드로 변경하고, 이후에는 해당 메서드를 더 이상 인터프리팅하지 않고 네이티브 코드로 직접 실행하는 방식이다.

네이티브 코드를 실행하는 것이 하나씩 인터프리팅하는 것보다 빠르고, 네이티브 코드는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 계속 빠르게 수행되게 된다. (pypy 와 동치)

추가 자료

RPython(Restricted Python)

RPython은 이런 실행 추적 JIT 컴파일을 C 로 구현해 툴체인을 포함한다. 그래서 RPython 으로 인터프리터를 작성하고 툴체인으로 힌트를 추가하면 인터프리터에 실행추적 JIT 컴파일러를 빌드한다. 참고로 RPython 은 PyPy 프로젝트 팀이 만든 일종의 인터프리터 제작 프레임워크(언어)다. 동적 언어인 Python 에서 표준 라이브러리와 문법에 제약을 가해 변수의 정적 컴파일이 가능하도록 RPython 을 만들었으며, 동적 언어 인터프리터를 구현하는데 사용된다.

이렇게 언어 사양(파이썬 언어 규칙, BF 언어 규칙 등)과 구현(실제 인터프리터 제작)을 분리함으로써 어떤 동적 언어에 대해서라도 자동으로 JIT(Just-in-Time) 컴파일러를 생성할 수 있게 되었다.

Leave a comment