LoginSignup
2
5

More than 3 years have passed since last update.

Cythonで行プロファイリング

Posted at

概要

Cythonコード「*.pyx」内の「cdef」関数内を行プロファイリングする方法

1. ライブラリのインストール

pip install line_profiler

2. pyxファイルの改変

2.1. ファイル冒頭に行プロファイル宣言追加

pyxファイルの先頭にコメント行として、プロファイル宣言を設定する

変更前)

# -*- coding: utf-8 -*-
#
import math
...

変更後)

# -*- coding: utf-8 -*-
#
# cython: profile=True
# cython: linetrace=True
# cython: binding=True
# distutils: define_macros=CYTHON_TRACE_NOGIL=1
import math
...

2.2. profileデコレータの呼び出し

cdef には関数デコレータが付けられないため、呼び出したい関数をprofileで囲む

変更前)

a = funca(a1, a2)

funcb(a, b1)

変更後)

pfa = profile(funca)
a = pfa(a1, a2)

pfb = profile(funcb)
pfb(a, b1)

2.3. cdef 関数を cpdef関数に変更

cdef 関数のままだと、stringsource.wrap でエラーになる

変更前)

cdef funca(a1, a2):
    return a1 * a2

変更後)

cpdef funca(a1, a2):
    return a1 * a2

3. setup.py の変更

3.1. Extentionのパラメーター追加

変更前)

       Extension("service.AService", sources=["service/AService.pyx"], include_dirs=['.']), 

変更後)

       Extension("service.AService", sources=["service/AService.pyx"], include_dirs=['.'], define_macros=[('CYTHON_TRACE', '1')]), 

3.2. cythonizeの変更

setup(name="*", cmdclass={"build_ext": build_ext}, ext_modules=cythonize(setup_ext.ext, annotate=True, \
      compiler_directives={'language_level': "3"}))

変更後)

setup(name="*", cmdclass={"build_ext": build_ext}, ext_modules=cythonize(setup_ext.ext, annotate=True, \
      compiler_directives={'language_level': "3", 'profile': True, 'linetrace': True, 'binding': True}))

4. コンパイル

setup.py のコンパイル時点で、kernprofを呼び出す

kernprof -l setup.py build_ext --inplace

5. プロファイル実行

kernprof -l -v executor.py

結果

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
   503                                               cpdef dict prepare_avoidance_dataset(self, int data_set_idx, str direction):
   504         2      29445.0  14722.5      0.1          logger.info("接触回避準備【No.%s - %s】", (data_set_idx + 1), direction)
   505
   506                                                   cdef int aidx, fno, from_fno, prev_block_fno, to_fno
   507                                                   cdef float block_x_distance, block_z_distance, x_distance, z_distance
   508                                                   cdef list all_avoidance_list, fnos, prev_collisions
   509                                                   cdef dict all_avoidance_axis, rep_avbone_global_3ds, rep_avbone_global_mats, rep_global_3ds, rep_matrixs, avoidance_list
   510                                                   cdef str avoidance_name, bone_name
   511                                                   cdef bint collision, near_collision
   512                                                   cdef BoneLinks arm_link, avodance_link
   513                                                   cdef ArmAvoidanceOption avoidance_options
   514                                                   cdef MOptionsDataSet data_set
   515                                                   cdef OBB obb
   516                                                   cdef RigidBody avoidance
   517                                                   cdef MVector3D rep_x_collision_vec, rep_z_collision_vec
   518
   519         2       1638.0    819.0      0.0          logger.copy(self.options)
   520                                                   # 処理対象データセット
   521         2         29.0     14.5      0.0          data_set = self.options.data_set_list[data_set_idx]
   522

(略)

後始末

プロファイリングが終わったら、コードを元に戻しておくこと

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5