インテル® VTune™ Amplifier XE で Python*/Cython 混在コードをプロファイルする

同カテゴリーの次の記事

インテル® Distribution for Python* の既知の問題

この記事は、インテル® デベロッパー・ゾーンに公開されている「Use VTune™ Amplifier XE to profile Python/Cython mixed code」の日本語参考訳です。


Python* はインタープリター言語であり、コンパイラーを使用してバイナリー実行コードを生成しません。Cython もインタープリター言語 (ただし C 拡張) ですが、ネイティブコードを生成できます。インテル® VTune™ Amplifier XE 2017 は、Python* コードと Cython コードの両方でホットな関数のレポートを完全にサポートしています。この記事では、Python* と Cython から関数を呼び出す単純な Python*/Cython 混在プログラムの例を用いて、インテル® VTune™ Amplifier XE で Python* コードと Cython コード中のホットな関数を特定し、表示します。

最初に、次のように Cython パッケージをダウンロードし、展開して、setup.py を実行します。
> python setup.py
# cython –version
Cython version 0.21.2

ファイル p1.py

    import os
    import math

def do_circle_py(longitude1,latitude1,longitude2,latitude2):
    radius = 3956 #miles
    cnt = 0

    while (cnt<10):
        x = math.pi/180.0
        a = (90.0-latitude1)*(x)
        b = (90.0-latitude2)*(x)
        theta = (longitude2-longitude1)*(x)
        c = math.acos((math.cos(a)*math.cos(b)) +
                     (math.sin(a)*math.sin(b)*math.cos(theta)))
        cnt = cnt + 1

    return radius*c

ファイル p2.py

    import os
    import timeit

longitude1, latitude1, longitude2, latitude2 = -72.345, 34.323, -61.823, 54.826
num = 500000

t_cy = timeit.Timer("c1.do_circle_cy(%f,%f,%f,%f)" % (longitude1,latitude1,longitude2,latitude2), "import c1")
t_py = timeit.Timer("p1.do_circle_py(%f,%f,%f,%f)" % (longitude1,latitude1,longitude2,latitude2), "import p1")

print "Pure cython function do_circle_cy()", t_cy.timeit(num), "sec"
print "Pure python function do_circle_py()", t_py.timeit(num), "sec"

ファイル c1.pyx

import math

def do_circle_cy(longitude1,latitude1,longitude2,latitude2):
    cdef float radius = 3956 #miles
    cdef float pi = 3.14159265
    cdef float x = pi/180.0
    cdef float a,b,theta,c
    cdef int cnt = 0

    while (cnt<10):
        a = (90.0-latitude1)*(x)
        b = (90.0-latitude2)*(x)
        theta = (longitude2-longitude1)*(x)
        c = math.acos((math.cos(a)*math.cos(b)) +
                     (math.sin(a)*math.sin(b)*math.cos(theta)))
        cnt = cnt + 1

    return radius*c

Cython ファイル (c1.pyx) をコンパイルし、p2.py によって呼び出される共有オブジェクト (c1.so) を生成します。
# cython c1.pyx
# gcc -c -g -fPIC -I/usr/include/python2.6 c1.c
# gcc -shared c1.o -o c1.so

インテル® VTune™ Amplifier XE 2017 以降を使用します。
# amplxe-cl -version
Intel(R) VTune(TM) Amplifier XE 2017 Beta (build 478468) Command Line Tool

Basic Hotspots 解析を実行してデータを収集します。
# amplxe-cl -c hotspots — python p2.py

インテル® VTune™ Amplifier XE の Bottom-up レポートから、Python* コードの do_circle_py() と Cython コードの __pyx_pf_2c1_do_circle_cy() がホットな関数であることが分かります。

コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。

関連記事