Pythonを簡単高速化!Cythonの実力とは?

Pythonは遅いと言われていますが、実はPythonを高速化する方法はたくさんあります。Numpy、Scipyを使って行列計算を行ったり、NumbaやPyPyと行ったツールでJITコンパイルしたり。

その中でもこの記事ではCythonというPythonのスーパーセットを使ってPythonを高速化する方法を紹介します。

Cythonを使うことで、Pythonにちょっと手を加えたコードをCにコンパイルしたり、Cの関数をPythonから呼び出したりと行ったことが手軽にできます。

この記事では

  • Cythonとは
  • Cythonの一番簡単な試し方
  • CythonとPythonの速度比較


などの話をまとめました。

この記事でCythonの勉強をスタートしましょう!

Cythonとは

cython_log

引用元: cython.org https://cython.org/

Pythonの遅さ

Pythonは他の言語と比べると、そこまで速い言語ではありません。

近年ではPythonのように手軽に書けるのにC並に速い言語としてJuliaが注目されていますが、そのJuliaの公式ページでは以下のような速度比較が掲載されています。

jula_GRAPH

引用元: High-Performance JIT Compiler -- julialang.org https://julialang.org/

このグラフを見てもわかるように、Pythonの速度はお世辞にも速いとは言えません。

Pythonを高速化する仕組み

Pythonはそんなに速くない、ということはわかりました。

ですが、実際にPythonは、Deep Learningや機械学習のような高度で高速な計算が求められる場面で使われています。

このような膨大な計算を行ったり速度が求められたりする場面では、生のPythonを使うのではなく、高速なライブラリに力を貸してもらうのがPythonの流儀です。

これらを支える技術としてNumPy、SciPyなどの行列計算ライブラリやその派生があります。

機械学習に必須!Pythonで高速に行列計算ができるNumPyに入門!
更新日 : 2020年3月3日

また、これらでもまだ足りない場合には、ChainerやTensorflowでGPUを使った高速化が行われます。

GPUはCPUと比べて圧倒的に速いので、大変な処理をそちらに回すことで、コントロールしているのがPythonであってもJavaであっても対して変わらない体感速度になります。

さて、こんなPython高速化界隈でPythonのコードをC/C++に変換することで高速化を目指すのがCythonです。

Cython

CythonはPythonにC言語の型が導入された言語です。

CythonコードをC/C++に変換してネイティブコンパイルするので、Pythonのようなインタプリタ型言語より速くなりそうですね。

Pythonっぽいコードの書き方をPythonic(パイソニック)と呼びますが、CythonではPythonicなままでC並の速度を得られることになります。

Cythonの使い方

cython1

Cythonを最も簡単に試すには、Jupyterを使います。ここではJupyterlabを使って、Cythonを試してみましょう。

インストール

まずはCythonをインストールします。

# Anaconda Pythonの場合
conda install cython

# それ以外のPythonの場合
pip install cython

これでCythonのインストールは完了です。

もしもJupyterがインストールされていない場合は、Jupyterもインストールしましょう。

# Anaconda Pythonの場合
conda install Jupyter

# それ以外のPythonの場合
pip install jupyter

これでJupyterのインストールもできました。Jupyterの使い方が不安な場合は、以下の記事を参考にしてください。

初心者必見!データサイエンスにオススメのJupyter Notebookとは?
更新日 : 2019年4月30日

JupyterlabでCythonを実行

実際にCythonを試してみましょう。

Jupyter NotebookやJupyterlabでCythonを試すには、まず最初に、JupyterにCythonを有効にさせるマジックコマンドを実行します。

%load_ext Cython

これをnotebookで実行。

jupyter_cython

あとは、Cythonで実行したいセルの先頭に以下のマジックコマンドを設置します。

%%cython

これで実行ができます。

Cythonの書き方と速度比較

cython_howto

フィボナッチ数列でスピードテストをしてみましょう。

Cythonの実験コード

条件は以下の4つです。

  • ただのPython(pure Python)で書いた関数
  • 関数1を単純にCythonにした関数
  • 関数2の引数に型アノテーションをつけた関数
  • 関数3の関数内の変数全てに型アノテーションをつけた関数
[関数1]
def fib_python(n):
    a, b = 0, 1
    for i in range(n):
        a, b = a + b, a
    return a
[関数2]
%%cython
def fib_cython(n):
    a, b = 0, 1
    for i in range(n):
        a, b = a + b, a
    return a
[関数3]
%%cython
def fib_typed_cython(int n):
    a, b = 0, 1
    for i in range(n):
        a, b = a + b, a
    return a

引数をみてください。

int n という感じで型情報がついていますね。変更点はここだけです。

[関数4]
%%cython
def fib_all_typed_cython(int n):
    cdef int a,b,i
    
    a, b = 0, 1
    for i in range(n):
        a, b = a + b, a
    return a

三行目のcdef int a,b,iというところで、a, b, iの各変数に型情報をつけています。cdefという宣言はCythonの中でのみ有効な宣言なので注意してください。

そのかなり超高速です!

速度比較

これらの関数の速さを、jupyterの%timeitで計測します。

%timeitは処理の速度を測るマジックコマンドです!

便利なので使ってみてください!

%timeit fib_python(5000)              # 関数1
%timeit fib_cython(5000)              # 関数2
%timeit fib_typed_cython(5000)        # 関数3
%timeit fib_all_typed_cython(5000)    # 関数4
[出力結果]
664 µs ± 85.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
415 µs ± 19.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
346 µs ± 5.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2.01 µs ± 235 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

なかなかおもしろい結果になりました。

分かりやすいように棒グラフに起こします。

cython_speedtest

型情報をたくさんつけたほうが高速になっていますね。何もつけていない関数2でもpure pythonと比べればかなり速いです。特にガリガリにチューニングした関数4は圧倒的です。

ですが、普段使いするには関数4のチューニング方法だとPythonらしさが足りないかもしれません。引数の型アノテーションをつけた関数3くらいまでのチューニングなら簡単ですし、Jupyter上で手軽に使うならオススメです!

まとめ

この記事ではCythonの紹介と速度比較を行いました。

Cythonは機械学習のライブラリでも使われているPython高速化ツールの虎の子です。

ここで紹介したもの以外にも更にCythonらしいチューニングをする方法はたくさんありますが、Cythonの威力、わかっていただけたんじゃないでしょうか。

ここで紹介しなかったチューニング方法や、Cythonを使った機械学習の実装がやってみたい!という方は、是非侍エンジニア塾のマン・ツー・マンレッスンを考えてみてください。

私もインストラクターとして所属しているプログラミングスクールです。レッスンや質問対応などであなたのプログラミングや人工知能などの勉強をサポートします!

LINEで送る
Pocket

「プログラミング、右も左もわからない…」という方にオススメ

当プログラミングスクール「侍エンジニア塾」では、これまで6000人以上のエンジニアを輩出してきました。

その経験を通してプログラミング学習に成功する人は、「目的目標が明確でそれに合わせた学習プランがあること」「常に相談できる人がそばにいること」「自己解決能力が身につくこと」この3つが根付いている傾向を発見しました。

侍エンジニア塾は上記3つの成功ポイントを満たすようなサービス設計に磨きをかけております。

cta_under_bnr

「自分のスタイルや目的に合わせて学習を進めたいな」とお考えの方は、ぜひチェックしてみてください。

書いた人

フクロウ

フクロウ

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