概要
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
(略)
後始末
プロファイリングが終わったら、コードを元に戻しておくこと