40163


`Python,PyQt,Pyside`で書いたコードを`Cython`で高速化  
したいと思っています。`python3.5`,`cython'0.24.1`

独立した関数レベルでは、実現したことが  
あるのですが、クラスそのものを丸ごと`Cython`化するの  
は、初の試みです。必要がなかったので。  
ちなみにメソッドを独立に`Cython`化  
するには、もうそのクラスのメソッドからはずして、  
独立した関数として、pyxモジュールに入れていました。  
**何のために必要としているのかというと、  
大量に抽象クラスをリストとして、取得したいと思っています。  
そのために、抽象クラスをCython化し、  
一つ一つの抽象クラスにかかる初期化速度を  
高速化したいのです。（簡略化しています。）**  
  
これが、pure Pythonのコード。

[code]

    from PySide import QtGui
    from PySide import QtCore
    import os
    import sys
    import re
    import random
    import another_module
    class Haru(Saru):
        def __init__(self,parent=None):
            super(Haru,self).__init__(parent=None)       
            self.IQ = 1000000000000000000000000000000000000  
            self.waru = Waru()
            self.karu = another_module.Tree()
            self.taipei = "taipei"
            self.malaysia = "malaysia"
            self.phillipine = "phillipine"
            self.bananas = [self.taipei,self.malaysia,self.phillipine]
        def eat(self):
            takeout = random.randint(0,2)
            get_banana = self.bananas[takeout]
            self.IQ += 300000000000000000000
        def sleep(self):
            sleeping = True
            self.IQ += 100000000000000000000
            time = 0
            while sleeping:
                self.IQ += 1000000000
                time += 1
                if time == 100:
                   break
    class Saru:
        pass
    class Daru:
        def fellows(self):
            fellows = [Haru() for i in range(300)] 
    class Waru:
        pass
    
[/code]

このとき、単純なビルトインタイプがあるときは、どうすればいいのかわかるのですが、  
大体すべてをCython化しようとすればどうすればいいのでしょうか。  
例えば、こちらが上のコードをcython化したものです。（未実行）

[code]

    from PySide import QtGui
    from PySide import QtCore
    import os
    import sys
    import re
    import random
    import another_module
    cdef class Haru(Saru):
        def __cinit__(self,parent=None):
            super(Haru,self).__init__(parent=None)    
            cdef int IQ
            cdef str taipei,malaysia,phillipine
            cdef list bananas
            # ここ！
    　　　　 cdef Waru waru
            cdef Tree karu
    
            self.IQ = 1000000000000000000000000000000000000  
            self.waru = Waru()
            self.karu = another_module.Tree()
            self.taipei = "taipei"
            self.malaysia = "malaysia"
            self.phillipine = "phillipine"
            self.bananas = [self.taipei,self.malaysia,self.phillipine]
        cdef void eat(self):
            cdef int takeout
            cdef str get_banana
    
            takeout = random.randint(0,2)
            get_banana = self.bananas[takeout]
            self.IQ += 300000000000000000000
        cdef void sleep(self):
            cdef bool sleeping
            cdef int time
            sleeping = True
            time = 0
            while sleeping:
                self.IQ += 1000000000
                time += 1
                if time == 100:
                   break
    class Daru:
        def fellows(self):
            fellows = [Haru() for i in range(300)] 
            return fellows
        """IQ=indulgence quality"""
    class Waru:
        pass
        """infinite indulgence"""
    
[/code]

クラスは、さまざまなタイプの複合体です。  
別のモジュールを利用したり、別の自分が独自で設定した  
型を使うことがよくあります。  
O'REILLY の [Cython]を読むと、  
大体このような状態であっていると思うのですが、  
抽象化インスタンスの元手となるclass自体をCython化したほうがいいでしょうか。  
それとも、下のように、抽象インスタンスを取得する関数をCython化した  
ほうがいいでしょうか？(fellowsをCython化)

[code]

    cdef class Daru:
       cdef list fellows(self):
           cdef list fellows
    　　　　cdef int num = 300
           cdef int i 
           fellows = [Haru() for i in range(num)] 
            return fellows
    
[/code]

としたり、特にこの場合は、  
リストの中にあるHaruをすべて、Haru型として  
宣言しておく方がいいのでしょうか。  
また、その場合いにはどう書けばいいのでしょうか。


CC BY-SA 3.0
2017-12-09T08:05:06.133
40153
2017-12-10T07:24:38.963
24284
question
python
Python クラスのCython化


Deepな話題らしいので、中々回答が付きにくいようですが、少し調べてみた結果を書きます。

1.使っているPythonとCythonの版数を上げる

Python v3.6とCython v0.27の組み合わせで、Type HintsとVariable Annotation  
サポートにより、ほぼ純粋なPythonコードをCythonで適切にコンパイルすることが  
できるようになったそうです。  
どこの部分をCython化するか悩んで試行錯誤するより、全体を対処できるのでは？

[Variable Annotation と Cython
でお手軽高速化](https://qiita.com/natsukium/items/99cffa5407aaf32a0b20#_reference-f9a4adbac6694d00946e)  
[Cython0.27で導入された型ヒント・変数アノテーション対応を試す](https://qiita.com/wrist/items/889696a507fbc8b392e4#_reference-
ac8d0292f6b69af3ded9)

何か事情があって直ぐには対応できないかもしれませんが、覚えておいて損は無いでしょう。

2.実際に何が遅いかを計測してから判断する

釈迦に説法でしょうが、質問には書かれていなかったので。  
迷っているなら、プロファイリングで遅い部分を検出するのが、対処方法決定の  
近道だと思います。

[Pythonスクリプトのパフォーマンス計測ガイド](https://yakst.com/ja/posts/42)  
[Pythonプロファイリング基礎](https://qiita.com/masashi127/items/ca092c13e1300f4f6ade)  
[Pythonにおけるプロファイリング ― コードの高速化のために](http://postd.cc/profiling-in-python/)  
[Pythonコードのプロファイリング](http://shkh.hatenablog.com/entry/2013/08/16/221205)  
[Python: profile/cProfile
モジュールでボトルネックを調べる](http://blog.amedama.jp/entry/2016/08/30/214718)  
[Python: line_profiler でボトルネックを調べる
](http://blog.amedama.jp/entry/2016/08/31/213229)

3.高速化およびCython化を行うにあたっての他の人の知見

これも釈迦に説法でしょうが、後から参照する人のために。

Cythonによる高速化を行う際に、どの部分に注目すれば良いかのまとめ記事です。  
[深入りしないCython入門](https://qiita.com/pashango2/items/45cb85390193d97523ca)  
[深入りしないCython入門 -2-](https://qiita.com/pashango2/items/fed0a1c06c7077639edc)

高速化全般  
[高速化のためのPython Tips](http://nonbiri-
tereka.hatenablog.com/entry/2016/09/01/072402)

Python/Cythonにcdef/NumPy/vectorなど色々組み合わせて計測実験  
[Pythonを高速化するCythonを使ってみた](http://kesin.hatenablog.com/entry/20120306/1331043675)


CC BY-SA 3.0
2017-12-10T07:24:38.963
40163
2017-12-10T07:24:38.963
26370
40153
answer