

これまで自分なりに色々と高速化を試行錯誤した結果がこちらなのですが、恥ずかしながらまだまだ改善の余地はあると思っております。  
こちらを更に高速化する方法をご教示いただけないでしょうか。

ご参考として、実際私が実行しているループ文はab,cde,,,が計17個あり、変数のrangeのほとんどが3ですので約4000万通りほど実行しております。

[code]

    for ab in range(3):
        for cde in range(2):
            for fg in range(3):
                for hi in range(3):
                    Return=np.r_[Return_AB[ab], #Return_ABの中身は(1,41)のnp.array
                                 Return_CDE[cde], #Return_CDEの中身は(1,41)のnp.array
                                 Return_FG[fg], #Return_FGの中身は(1,41)のnp.array
                                 Return_HI[hi]] #Return_HIの中身は(1,41)のnp.array
                    Return_total = np.sum(Return, axis=0)
                    Return_dif = Return_total-BM #BMは(1,41)のデータフレーム
                    Num0 = max(Num0_AB[ab],Num0_CDE[cde],Num0_FG[fg],Num0_HI[hi]) #4~8の値
                    Win_Pro = (Return_dif.iloc[:,Num0:] > 0).sum(axis=1) / (Number_Date-Num0)
                    if Win_Pro.item() < 1:
                        continue
                    Cum_return = np.prod(Return_dif.iloc[:,Num0:]+1, axis=1)-1
                    if Cum_return.item() < 0.1:
                        continue
                    TE = Return_dif.iloc[:,Num0:].std(axis=1)
                    Result.append([Win_Pro.item(),Cum_return.item(),TE.item(),Num0,ab,cde,fg,hi])
    
[/code]


CC BY-SA 4.0
2018-11-11T14:58:04.110
50217
2018-11-12T09:35:57.547
2018-11-11T15:56:32.000
3060
30914
question
python python3
多重ループを高速化する方法


この質問のケーズでは、繰り返しをやめてNumpyやPandasのベクトル計算を使うのは必要なメモリーが莫大になるで、繰り返し処理はそのままにして、`Numba`か`Cython`を使って高速化するのがいいと思われます。

`Numba`は簡単に使えるのでとりあえず`Numba`を試してみてはどうですか。

[code]

    import numba
    
    @numba.jit
    def calc():
        NMAX = 10000000 #オーバフローしない数値にしておく
        Win_Pro = np.zeros(NMAX) 
        Cum_return = np.zeros(NMAX) 
        TE = np.zeros(NMAX)
        N = np.zeros(NMAX, dtype=int)
        A = np.zeros((4, NMAX), dtype=int)
    
        int n = 0
        for ab in range(3):
            for cde in range(2):
                for fg in range(3):
                    for hi in range(3):
                        Return_total = Return_AB[ab] + #Return_ABの中身は(41)のnp.array
                                     Return_CDE[cde] + #Return_CDEの中身は(41)のnp.array
                                     Return_FG[fg] + #Return_FGの中身は(41)のnp.array
                                     Return_HI[hi] #Return_HIの中身は(41)のnp.array
                        Return_dif = Return_total-BM #BMは(41)のnp.arrayに変換しておく。PandasのDataFrameとSeriesは。df.valuesでnp.arrayに変換できる
                        Num0 = max(Num0_AB[ab],Num0_CDE[cde],Num0_FG[fg],Num0_HI[hi]) #4~8の値
                        Win_Pro[n] = (Return_dif.iloc[:,Num0:] > 0).sum() / (Number_Date-Num0)
                        if Win_Pro[n] < 1:
                            continue
                        Cum_return[n] = np.prod(Return_dif.iloc[:,Num0:]+1) - 1
                        if Cum_return[n] < 0.1:
                            continue
                        TE[n] = Return_dif.iloc[:,Num0:].std()
                        N[n] = Num0
                        A[n] = np.array([ab, cde, fg, hi]) 
                        n += 1
    
        return Win_Pro[:n], Cum_return[:n],TE[:n], N[:n], A[:n,:] 
    
[/code]

`Return=np.r_`で`ndarray`を結合していますが、それを省略して直接加算した方が速いと思います。  
また、Resultはリストのリストになっていますが、リストのリストは処理が遅いので`ndarray`に変更してみました。`pd.concat`を使ってPandasのDataFrameにしておくとその後の利用に便利です。

`Numba`を使っても遅い場合には、`Cython`が使えます。`Cython`の利用については、次の公式マニュアルが参考になると思います。

・Cython [Working with
NumPy](https://cython.readthedocs.io/en/latest/src/tutorial/numpy.html)  
・Pandas [Enhancing Performance](https://pandas.pydata.org/pandas-
docs/stable/enhancingperf.html)

`Cython`の場合もそれほど難しいことはないですが、変数の型宣言に手間がかかります。例えば、Jupyter Notebookを使うのであれば、まず
Cythonのマジック関数をインポートして

[code]

    %load ext Cython
    
[/code]

次のようなコードでとりあえず動きます。

[code]

    %%cython
    def calc(Return_AB, Return_CDE, Return_FG, ,Num0_AB, Num0_CDE, Num0_FG, Num0_HI, BM):
    # 以下略
    
[/code]

あとは、変数に型宣言をしていくと高速に処理できるようになります。


CC BY-SA 4.0
2018-11-12T09:29:32.790
50240
2018-11-12T09:35:57.547
2018-11-12T09:35:57.547
15171
15171
50217
answer