高速動作するPython「PyPy」とは?概要と速度をチェック

PyPyって何?
Pythonより高速だって聞いたけど、どれくらい速いの?

Python(CPython)より高速に動作するPython実装のPyPy、興味がある方は多いんじゃないでしょうか。

こんにちはフクロウです。Pythonのインストラクターをやっています。

この記事ではJITコンパイルで高速に動作するPython実装のPyPyについて、概要と実際のスピードテストを紹介します。

結構簡単に使えるPyPy、使わないのは損です!是非試してみましょう。

この記事はこんな人のために書きました。

  • PyPyに興味がある方
  • PyPyとCPythonの速度比較が見たい方
  • pyenvをインストール済みの方

目次

PyPyとは

cython.org

PyPyとは、Pythonの実装の一つで、CPyhon(いわゆる普通のPython)よりも高速にプログラムを動作させる事ができます。

まず、RPythonというCPythonのサブセットがあります。これはつまり制限付きのCPythonで実装されたPython処理系です。

そしてそのRPythonを使って実装されたのがPyPyになります。

PyPyのプログラムはJust-in-Time(JIT)コンパイルという、実行時にコードのチャンクを実行時に逐一コンパイルするシステムを使って高速化されています。JITコンパイルは何度も使われるコードを最適化するため、Pythonのコードでもかなり早く動かすことができます。

以下の記事より引用:

PyPyは他のPython実装と同様にpyenvから簡単に利用できます。次の章でインストールを紹介するので、一緒に試してみましょう。

PyPyの使い方

インストール

PyPyの最も簡単なインストールには、pyenvを使います。pyenvをインストールしていない方はここをチェックしてください。

まずはpyenv install –listでインストールできるPythonのバージョンを確認します。

$ pyenv install --list

  ...
  pypy3.5-5.9.0-src
  pypy3.5-5.9.0
  pypy3.5-5.10.0-src
  pypy3.5-5.10.0
  pypy3.5-5.10.1-src
  pypy3.5-5.10.1
  pypy3.5-6.0.0-src
  pypy3.5-6.0.0
  ...

この中から最新版をインストールしましょう。

$ pyenv install pypy3.5-6.0.0

Downloading pypy3-v6.0.0-osx64.tar.bz2...
-> https://bitbucket.org/pypy/pypy/downloads/pypy3-v6.0.0-osx64.tar.bz2
Installing pypy3-v6.0.0-osx64...
Installed pypy3-v6.0.0-osx64 to /Users/Samurai/.pyenv/versions/pypy3.5-6.0.0

あとは適当なディレクトリでpyenv local 使いたいPythonのバージョンとしてやればPypyが使えます。

注意

PyPyは普通のPythonと同じ書き方で利用できます。ただ、C言語で書かれた一部のライブラリは利用できないことに注意してください。

ただし、NumPyなど個別に対応されているものについては利用可能です。

PyPyのスピードテスト

PyPyは普通のCPythonより高速であると書きましたが、どのくらい高速なのか確認してみましょう。ここでは、フィボナッチ数列を出すプログラムfib.pyと最大公約数を計算するプログラムgcb.pyを用意しました。

[fib.py]

#-*- using:utf-8 -*-
import time

def fib_python(n):
    a, b = 0, 1
    for i in range(n):
        a, b = a + b, a
    return a

dump = []
max_iter = 100000
for i in range(max_iter):
    start = time.time()
    
    fib_python(5000)
    
    elapsed_time = time.time() - start
    dump.append(elapsed_time)

print(sum(dump)/max_iter)

[gcb.py]

#-*- using:utf-8 -*-
import time

def gcd_python(x, y):
    if y == 0:
        return x
    else:
        return gcd_python(y, x % y)
    
dump = []
max_iter = 100000
for i in range(max_iter):
    start = time.time()
    
    gcd_python(10000,325)
    
    elapsed_time = time.time() - start
    dump.append(elapsed_time)

print(sum(dump)/max_iter)

このプログラムはそれぞれ、timeモジュールで計算時間を測定しています。max_iterの数字を変更することで、ループ回数を変更できます。

pyenv localでpypyとcpythonそれぞれに変更して実行してみてください。

ちなみに、ここでは以下の環境で実験を行いました。

$ python -V
Python 3.7.2

$ pypy -V
Python 3.5.3 (fdd60ed87e94, Apr 24 2018, 06:10:18)
[PyPy 6.0.0 with GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.1)]

それでは実行結果を見てみましょう。

$ python fib.py
0.0005311285495758056

$ pypy fib.py # pyenv localでpythonを変更した場合はpython fib.pyでOKです。
0.0002192509412765503

$ python gcd.py
8.079719543457031e-07

$ pypy gcd.py
1.8852710723876953e-07

それぞれの結果を見てみると、pypyの方がfib.pyで約2.4倍gcb.pyで約4.3倍高速です。全くコードを変えていないのにもかかわらず、これだけ差がでるのはすごいですね!

さて、今回のテストでは分かりやすい結果が出ましたが、PyPyにも高速化の得意不得意があります。是非これ以外のコードでもテストを試してみてください。

まとめ

この記事ではPythonのプログラムを高速に動作させる実装であるPyPyを紹介しました。

PyPyはpyenvから簡単に試すことができるPython実装で、JITコンパイラのおかげで素のCPythonよりも数倍高速です。

Pythonの高速化にはこれ以外にも、Cythonを使う方法やNumPyを使う方法などがあります。

その中でもPyPyは学習コストが少ない高速化方法だと思います。是非使ってみてください!

この記事を書いた人

第一言語はPythonです。
皆さんRustやりましょう。

目次