Posted at

Python標準実装より速い!?Oracleが作ったGraalPythonをJython・CPythonとベンチマークしてみた!!


GraalVM・GraalPythonとは

image.png

GraalVMは2018年4月27日にOracleから公開された仮想マシンです.


GraalVM is a universal virtual machine for running applications written in JavaScript, Python, Ruby, R, JVM-based languages like Java, Scala, Clojure, Kotlin, and LLVM-based languages such as C and C++.

GraalVMはJavaScript,Python,Ruby,R,JavaやScala,Clojure,KotlinのようなJVMベースの言語,CやC++のようなLLVMベースの言語で書かれたアプリケーションを動かすための仮想マシンです.


ちょっと何を言ってるかわからないと思いますが,私も分かりませんでした.

GraalVMは本当にこの通りで,jsやPythonのようなスクリプト言語も動き,ScalaやKotlinのようなJVM言語も動き,LLVMベースのバイナリも動く仮想マシンです.

公式サイトを見てもらうと一番早いのですが, 

image.png

本当に信じられないぐらいの数の言語が動く環境が公開されています.

これらの中に,GraalPythonというGraalVM上で動くPython実装が公開されています.

GraalPythonはCPythonよりどれくらい早いのか?

ということをベンチマークしていきたいと思います.


GraalPythonの導入

非常に簡単です.

公式サイトのダウンロードに行き,tar.gzをダウンロードしていきます.

あとは

# 解凍

$ tar xvf graalvm-ce-1.0.0-rc8-linux-amd64.tar.gz

# Pythonバインディングのダウンロード
$ ./graalvm-ce-1.0.0-rc8/bin/gu intall python

# GraalPythonの実行
$ ./graalvm-ce-1.0.0-rc8/bin/graalpython
Please note: This Python implementation is in the very early stages, and can run little more than basic benchmarks at this point.
>>>

これだけで導入できます!!


Jythonって何?

以前に書いた記事で,Jythonについては取り上げたことがあります.

Pythonマイナー環境列伝 ~あなたはいくつのPython環境を知っているか?~

image.png

いわゆるJVM上で動くPythonの実装です.普通のPythonと違い,Javaのライブラリが使えたりします.

過去に作られたJVM上で動く,Java実装のPythonはどこまで健闘できるのか?

ということも検証してみます.

導入方法もUbuntuなら簡単でこんな感じで導入できます.

$ apt-get install jython

$ jython --version
Jython 2.7.1

しかし,現在,Jythonは開発が停止しているらしく,Pythonの2.7系までしか対応していません.


ベンチマーク

今回,比較対象とするCPythonは

$ python3 --version

Python 3.6.3

実行する内容は前の記事を参考にやっていこうと思います.

GoとPythonとGrumpyの速度ベンチマーク ~Googleのトランスパイラはどれくらい速い?~


モンテカルロ法による円周率の求解によるベンチマーク


実験方法

プログラミングの教本でもよくある円周率のモンテカルロ法による計算をベンチにしました.

よい解説があったので引用で貼っておきます.

試行回数により,処理時間がどのように変化するかを観察します.

image.png

引用:モンテカルロ法と円周率の近似計算


実装


monte_py.py

#coding:utf-8

import random
import sys

if __name__=="__main__":
num = int(sys.argv[1])
c = 0
for i in range(num):
x = random.random()
y = random.random()
if x * x + y * y <= 1.0:
c += 1

print(4.0*c/num)



結果

繰り返し回数
Python[sec]
Jython[sec]
GraalPython[sec]

1000000
0.941
7.139
4.105

2000000
1.858
9.553
4.816

3000000
2.988
13.913
4.969

4000000
4.022
14.959
5.141

5000000
5.435
21.144
6.349

6000000
7.026
25.413
6.774

7000000
8.701
34.169
7.361

8000000
13.682
61.787
13.847

9000000
15.613
40.517
7.044

10000000
10.684
33.798
5.451

11000000
11.394
26.569
5.402

12000000
12.661
38.839
6.846

13000000
17.158
63.671
7.655

14000000
16.572
47.804
6.156

15000000
19.187
57.862
7.904

16000000
25.037
87.531
7.333

17000000
19.235
54.170
6.315

18000000
18.775
68.362
8.148

19000000
29.085
68.262
6.802

20000000
21.175
65.696
6.590

image.png

GraalPython > CPython >> Jython


考察

繰り返し回数が小さいときにはCPythonが速いですが,繰り返し回数が大きくなってくるとGraalPythonのほうが速い.という傾向がみられました.一方でJythonはすごく遅い.

こう見るとGraalPythonは中でJITによる高速化が効いているようですね.それによりこのように高速化されているのではないでしょうか.JVMにもJITが入っているので速くなっても不思議ではないのですが,Jythonのほうは速くなりませんね・・・


竹内関数によるベンチマーク


竹内関数とは

竹内関数(たけうちかんすう)は、プログラミング言語処理系のベンチマークなどに使われる、再帰的に定義された関数である。

image.png

参考:竹内関数


実験方法

Tarai(n,n-1,0)という形で竹内関数を呼び出し,nの大きさと処理時間にどのような変化があるのかを観察する.


実装


tarai_py.py

#coding:utf-8

import sys

def tak(x,y,z):
if x<=y:
return y
else:
return tak(tak((x - 1),y,z), tak((y - 1),z,x), tak((z - 1),x,y))

if __name__=="__main__":
a,b,c = map(int,sys.argv[1].split())
print(tak(a,b,c))



結果

n
CPython[sec]
Jython[sec]
GraalPython[sec]

10
0.370
19.500
1.679

11
2.167
23.383
2.448

12
11.929
16.079
2.062

13
58.507
24.814
5.823

14
453.833
115.069
43.099

image.png

nが小さいとき

CPython > GraalPython > Jython

nが大きいとき

GraalPython >> Jython > CPython


考察

面白いグラフになりました.nが小さいときはCPythonが速いですが,nが大きくなるにつれ,JythonやGraalPythonが速くなる.という結果になりました.これはJITが効いているように思います.

以前にも似たような検証をしたことがあって,C言語で作った竹内関数のベンチマークとJavaで作った竹内関数のベンチマークをしたことがあります.その時も,nが大きくなった時,Javaのほうが速くなる.といったことが起こりました.このような再起が多く行われる関数だと,Javaのほうが速くなる.ということはままとしてあるようです.そのため,JVMベースのJythonや,それを踏襲したGraalVMを使ったGraalPythonがCPythonを凌駕する速度になることは,割とありえることなのかもしれません.


まとめ

もともとJVM周りのスクリプトの対応について調べていたところ,GraalPythonを見つけました.そこでGraalVMを知り,あれ?これってJVMと何が違うんだっけ?という疑問から,過去にあったJythonとベンチマークの比較をしてみました.

GraalPythonを少し触ってみましたが,やはり少し機能が足りないな.という気持ちもあります.例えば,python3にはビルトインの関数で,inputがありますが,GraalPythonにはありません.(おそらくinput関数の実装をGraalVM上で実装するのは大変そうですが・・・)

それにしても,時間がかかるような処理.Pythonで5秒以上かかるようなCPUバウンドな処理をすると,GraalPythonのほうが速くなる.というのは驚きでした.

まだいろいろなライブラリ周りと合わせて使っていないので,どんなバグが起こるかわかりませんが,一度いろんなライブラリを試してみるのはいかがでしょうか?