나무모에 미러 (일반/밝은 화면)
최근 수정 시각 : 2024-08-17 12:06:43

PyPy


파일:나무위키+유도.png  
파이파이은(는) 여기로 연결됩니다.
엔드로~!의 등장인물에 대한 내용은 파이 파이 문서
번 문단을
부분을
, 냥코 대전쟁의 캐릭터 파이파이에 대한 내용은 레드 바스터즈 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
, 에 대한 내용은 문서
번 문단을
번 문단을
부분을
부분을
참고하십시오.
파이파이
PyPy
파일:pypy-logo.svg
<colbgcolor=#ffffff,#1f2023><colcolor=#193440,#D1D5CA> 개발 Armin Rigo
라이선스 MIT 라이선스
최초 공개 2007년 중순
안정 버전 7.3.16 (2024년 4월 23일 릴리즈)
파일:홈페이지 아이콘.svg | 파일:GitHub 아이콘.svg파일:GitHub 아이콘 화이트.svg | 파일:유튜브 아이콘.svg |
1. 개요2. 상세3. 어떻게 구현하나4. JIT, 그리고 마개조5. 호환성6. 예제7. 스탠드얼론 실행파일 만들기

[clearfix]

1. 개요

2007년에 처음 발표된 Python의 언어 구현 중 하나로, C로 짜인 기존의 CPython과 달리 Python으로 Python을 만드는 프로젝트이다.[1] 여기만 보면 뭔가 이상한 짓 하는 프로젝트 내지 실험적인 프로젝트처럼 느껴지겠지만, 이 프로젝트의 진짜 놀라운 점은 기존 CPython보다 전혀 느리지 않을 뿐더러, 오히려 성능면에서 CPython을 능가하고 있다는 점이다. 나아가 이 링크에서 보이는 대로, 계속해서 빨라지고 있다! 표준 구현인 CPython과의 속도비교. PyPy를 개발하면서 지속적으로 업데이트 하고 있다.

2. 상세

PyPy는 단순히 Python을 가지고 장난을 하려고 시작한 프로젝트가 아니다. Psyco라고 하는, 기존 파이썬 위에다가 Just-In-Time 컴파일을 구현해서 실행성능을 높이는 프로젝트가 있었는데, 이걸 개발하던 Armin Rigo라는 사람이 아예 JIT 컴파일을 하는 파이썬을 처음부터 다시 구현하기로 생각했다. 그래서 2003년부터 PyPy 개발을 시작하여 유럽연합의 연구자금 지원을 받아가며 지금도 개발하고 있다.

3. 어떻게 구현하나

인터프리터 방식의 Python을 가지고 파이썬으로 돌리는 파이썬을 어떻게 만들었을까. PyPy의 접근법은 이렇다.
  1. 먼저 RPython이라고 하는, 파이썬 문법을 엄격하게 만들어 컴파일이 되게 만든 해석기(translate.py)를 Python 코드로 작성한다.[2]
  2. RPython의 효과적인 컴파일을 위해 다른 언어로 툴체인을 만든다.[3]
  3. Python 구현(런타임)을 RPython 문법으로 작성한다.
  4. 3에서 만든 구현을 1 또는 2에서 만든 RPython 해석기로 컴파일한다.
  5. 4으로 만든 후보를 이전 또는 다른 구현과 비교(성능 측정), 만족스럽지 않으면 수정한다.(nightly builds)
  6. 5에서 만족스러운 결과를 냈다면 출시하고 1 또는 2부터 다시 시작한다.(release)
처음 한번만 기존 파이썬의 도움을 받으면 그 다음부터는 스스로 만든 구현으로 저 과정을 자체적으로 계속 반복할 수 있다. 이러한 이유로 로고가 우로보로스인 셈. 이게 얼핏 보면 '닭이 먼저냐 달걀이 먼저냐' 같은 것으로 착각할 수도 있지만, 이런 식의 접근법은 실제로 프로그래밍 언어를 제작할 때 해당되는 사항이다. 일례로 오래 전에 만들어진 유명 C/C++ 컴파일러인 GCC도 C/C++로 작성되었다. 파이썬이 스크립팅 언어이기 때문에 일견 특이해보이는 것일 뿐, 인터프리터는 어차피 컴파일된 상태로 돌아가므로 같은 원리다.간단히 보자면 더 좋은 장비의 개발을 위해 기존의 장비를 사용하는 것과 다름이 없다. 짱돌로 뗀석기를 만들고, 뗀석기로 간석기를 만들었던 것 처럼 인류 역사에 고고히 전해져오는 방법론 을 사용하고 있는 것이다.

이런 식으로 어떤 언어로 자기 자신을 구현하는 것을 부트스트래핑(Bootstrapping) 또는 부팅(Booting)[4]이라고 하는데, 이렇게 하는 이유는 처음부터 작업하는 것보다 생산성이 좋기 때문이다. 처음부터 어셈블리어로 작업하면 이론상 최강의 성능을 발휘할 수는 있으나 그 가능성은 매우 낮고 생산성도 최악이다.(최적화가 그래서 힘들다.) 이 때문에 대부분의 프로그래밍 언어도 초창기에는 어셈블리어나 다른 저급언어의 도움을 받지만, 일정 단계를 넘어서면서 발전에 한계가 오면 스스로의 컴파일러/인터프리터를 제작하게 된다. Haskell 컴파일러인 GHC와 C/C++ 컴파일러인 GCC가 대표적인 예. 물론 생산성에 중점을 두기 때문에 성능이 눈에 띄게 빨라지는 일은 드물고, 단지 우연한 발견 등 여러 이유로 성능이 향상되는 것 뿐이다. PyPy의 경우 Python의 한계를 극복하기 위해 정적인 컴파일이 가능한 RPython을 따로 만들었고 뒤에도 후술한 것처럼 성능 향상을 위해 7년이라는 긴 세월을 소모했는데, 이것도 어셈블리어로 처음부터 개발하는 것보다는 짧은 것이다.[5]

4. JIT, 그리고 마개조

PyPy는 RPython으로 이루어진 Python 인터프리터와 (역시 RPython으로 이루어진) C, .NET, JVM 등을 타게팅한 해석 툴체인으로 이루어져 있는데, 해석 툴체인은 해당 플랫폼을 위한 효율적인 코드를 생성하는 데 초점이 맞춰져 있으며, Tracing JIT을 통해 인터프리터 단위의 JIT 컴파일이 가능하므로, CPython보다 빠른 결과물이 나오게 된다.

여기까지만이어도 그냥 기존 구현보다 그다지 느리지 않은 파이썬 구현을 다른 언어의 도움 없이 파이썬 스스로 만든 셈이지만, 여기서 하나가 더 들어간다. Armin Rigo가 뭐 만들던 사람이라는 내용이 위에도 있지만 PyPy는 JIT compiler이다. 그것도 그냥 JIT가 아니라 Meta tracing JIT라는 괴랄한 것을 구현했는데, JIT이 필요한 부분에 약간의 힌트 코드를 넣으면 RPython 해석기가 알아서 JIT compile이 되는 언어 구현을 만들어준다. 다른 언어 구현들이 JIT 좀 해보자고 무지막지한 삽질을 하는 것과 달리[6] 거의 공짜와 다름없다.

하지만, 사실 만들고 나서 보니 그렇게 보이는 거고 PyPy는 그냥 JIT를 구현한 게 아니라 JIT 구현을 만들어주는 컴파일러를 구현한 셈이 되므로 실제 작업은 훨씬 더 어려웠을 것이다. 당장 PyPy가 CPython보다 빨라진 게 PyPy 1.3부터인데, 그게 2010년 중순이다.[7] 다시 말해, 7년 동안 아무도 알아주지 않던 '진화'가 드디어 빛을 본 셈. 그리고 본인들도 "우리는 영웅이 아니며, 단지 인내심이 많았을 뿐이다."라고 말하고 있다. 잠시 PyPy 개발팀의 근성에 경의를 표하자.

여담으로, 이 녀석의 해석은 사람만 힘드는 게 아니라 컴퓨터도 힘든 모양이다. 써 볼 사람들은 시간이 남아돌고 사용하는 컴퓨터가 어지간히 고사양이 아니라면 미리 컴파일된 것을 받아 사용하자. 사실 소스에서 직접 빌드할 생각을 했다면 이미 시간은 상관이 없을 것이다 CPython을 통한 Bootstrapping에 엄청난 시간과 메모리를 요구한다. 준비물이 모두 갖춰진 상태에서 PyPy 2.2.1 달랑 하나를 빌드하는 데에 모질라 파이어폭스와 그것이 의존하는 모든 다른 패키지들을 빌드하는 것보다 시간이 더 걸린다! Core i7 3.33GHz, 다른 작업 방해 없이 코어 1개 풀사용, 8GB 램 기준으로 최소 3시간은 각오해야 한다. 64비트 CPython으로 컴파일하다 보면 Python 프로세스 하나가 램을 5GB 가까이 처묵처묵하는 것도 볼 수 있다.

그래도 이런 구조로 만든 덕분에 보너스로, RPython 컴파일을 할 때 목적 타겟을 다르게 주면 다른 플랫폼으로도 돌아가는 파이썬 구현이 나오고, 똑같은 PyPy 소스코드로 CPython 같은 것도 나오며, Jython 같은 것도, IronPython 같은 것도 나온다. 추가로 코루틴을 쓰는 Stackless Python 같은 것도 비슷한 방법으로 만들 수 있어서 Stackless Python 개발하던 Christian Tismer가 아예 PyPy 개발팀에서 같이 일하고 있다.[8]

5. 호환성

PyPy 개발팀의 호환성 기준은 매우 심플해서, 이유 여하를 막론하고 CPython에서 되는 게 PyPy에서 안 되면 그냥 PyPy 버그다.

예전에는 PyPy는 구조적 문제로 인해서 64비트 윈도우용으로 컴파일 할 수 없었다. 물론 32비트용으로는 제공되므로 윈도우와의 호환성에 큰 문제가 되지는 않는다. 하지만 3.7 버전부터 문제를 해결해 64비트 윈도우로도 배포한다. #

6. 예제

몬티 홀 문제로 테스트 해 보자.
#!syntax python
import time
import random

def populate_doors(): # put a car behind one door
	door=['goat', 'goat', 'goat']
	door[random.randint(0,2)]='car'
	return door

wins = 0
losses = 0
time_start = time.time()

# playing the game 100,000 times:
for x in range(100000):
	doors=populate_doors()
	first_choice=random.randint(0,2) # choose a random door
	for y in range(3): # reveal first losing, unchosen door
		if doors[y] != 'car' and y != first_choice:
			doors[y] = 'out'
			break
	if doors[first_choice] == 'car':
		losses = losses + 1 # contestant switched to losing door
	else:
		wins = wins + 1 # contestant switched to winning door
time_finish = time.time()

print("All choices were switched.")
print("Wins: ", wins)
print("Losses: ", losses)
print("Elapsed time: ", time_finish-time_start)

코드 출처[9]

PyPy가 약 25[10] 빠르다. 물론 코드에 따라 배율에 차이가 있고 가끔씩 더 느린 코드도 있지만 어지간한 경우엔 PyPy쪽이 빠르다.[11]

7. 스탠드얼론 실행파일 만들기

py2exe, PyInstaller를 비롯해 다양한 스탠드얼론 실행파일 제작 프로그램이 지원되는 CPython과 달리 PyPy용으로 지원되는 스탠드얼론 실행파일 제작 프로그램은 현재 사실상 PyOxidizer가 유일하다.


[1] 부트스트래핑이라고 한다.[2] RPython는 Python의 일부만 구현한 언어(부분 언어)이기 때문에 모든 RPython 코드는 Python 코드이기도 하다. (반대는 성립하지 않는다.)[3] 시뮬레이터에뮬레이터를 제작하는 때에도 이 과정을 반드시 거친다.[4] 운영체제의 부팅과 같은 어원으로, 뮌히하우젠 남작의 모험 이야기에서 유래했다.[5] 컴퓨터 하드웨어의 발전도 마찬가지다. 처음 IC나 LSI를 설계할 때는 레이아웃을 손으로 그렸지만, 지금 나오는 칩들은 손으로 하기에는 회로의 규모가 지나치게 크기 때문에 전부 CAD로 개발하고 있다.[6] 인터프리트나 바이트코드 컴파일 방식을 가지는 언어 구현 사이에 JIT를 실용적으로 하는 구현은 OracleJVM이나 Microsoft.NET Framework 정도밖에 없다. 둘 다 돈 좀 쓰고 다닐 것 같은 느낌이 들지 않는가?[7] 위에도 있지만 2003년에 개발을 시작했다.[8] 여담이지만 이 두 사람이 모여서 만든 또 하나의 작품이 greenlet인데, Psyco처럼 기존의 CPython에다가 마개조를 해서 원래 지원 안 되는 코루틴을 만들어 올리는 라이브러리다... 참고@. 추가적으로, 코루틴은 파이썬 3.4부터 내장되며, 3.5부터는 async과 await이라는 키워드도 탑재된다.[9] 현재 불능 http://www.danielveazey.com/tag/monty-hall-problem/, 가장 유사한 곳 https://matthew-brett.github.io/dsfe/chapters/extra/monty_hall_lists@[10] Python 2.7.11 x86_64, PyPy 5.1.0 x86_64 기준.[11] 2021년 시스템 64비트, pypy 3.7.9와 python 3.9.2로 측정결과, pypy가 거의 2배 정도 빠름