質問内容
ボトルネックとなっている配列累積加算ループの処理速度向上を検討しております。
ロジックをイジったり色々試行してみましたが、期待する速度向上はできませんでした。
なお、Cythonでは2倍程度の速度向上がみられましたが、これより速くする方法を見出しているところです。徹夜して奮闘していますが、なかなか名案が浮かばなく...
大変お手数ですが、何かアドバイス等ありましたらお願いいたします。
試したこと
■ Cython ・・・2倍程度速度向上しましたがこれ以上の速度向上を望んでいます。
■ numba(jit) ・・・殆ど変化しませんでした。
今後試そうと思っていること
■ マルチプロセス化・・・ソースが煩雑になり可読性が失われるため最終手段と考えております...
サンプルコード
Python
1import numpy as np 2import time as t 3 4np.random.seed(0) 5a = np.random.rand(2, 2, 10000) 6b = np.random.rand(10000, 10000) 7c = (np.array(list(range(10000)))).astype('i') 8#x = np.zeros(10000).astype('i') 9x = (np.random.rand(10000) * 1000).astype('i') 10y = np.full(10000, 1000).astype('i') 11 12start = t.time() 13 14num = 10000 15img = np.zeros((10000, 10000)) 16 17# add 18out = [a[:, :, i] * b[c[i], 0] for i in range(num)] 19 20#for i in range(num): 21# img[x[i] : x[i] + 2 , y[i] : y[i] + 2 ] += a[:, :, i] * b[c[i], 0] 22for i in range(num): 23 img[x[i] : x[i] + 2 , y[i] : y[i] + 2 ] += out[i][:][:] 24 25print('time : ' + str(round((t.time() - start),5)) + ' [sec]')
サンプルコード(Cython化)
以下を実行して頂くとコンパイルおよび処理が実行されます。
$ python setup.py build_ext --inplace ; python main_test_20190524.py
test_20190524.pyx
Cython
1import cython 2import numpy as np 3cimport numpy as np 4 5ctypedef np.int32_t np_int_t 6ctypedef np.float64_t np_float_t 7 8@cython.boundscheck(False) 9@cython.wraparound(False) 10 11cpdef np.ndarray[np_int_t, ndim=1] test_20190524( 12 np.ndarray[np_float_t, ndim=3] a, 13 np.ndarray[np_float_t, ndim=2] b, 14 np.ndarray[np_int_t, ndim=1] c, 15 np.ndarray[np_int_t, ndim=1] x, 16 np.ndarray[np_int_t, ndim=1] y): 17 18 cdef np.ndarray[np_float_t, ndim=2] img 19 cdef int i, num 20 21 num = 10000 22 img = np.zeros((10000, 10000)) 23 24 # add 25 out = [a[:, :, i] * b[c[i], 0] for i in range(num)] 26 27 #for i in range(num): 28 # img[x[i] : x[i] + 2 , y[i] : y[i] + 2 ] += a[:, :, i] * b[c[i], 0] 29 for i in range(num): 30 img[x[i] : x[i] + 2 , y[i] : y[i] + 2 ] += out[i][:][:] 31 32 return img
main_test_20190524.py
Python
1import test_20190524 as cy 2import numpy as np 3import time as t 4 5def main(): 6 np.random.seed(0) 7 a = np.random.rand(2, 2, 10000) 8 b = np.random.rand(10000, 10000) 9 c = (np.array(list(range(10000)))).astype('i') 10 x = (np.random.rand(10000) * 1000).astype('i') 11 y = np.full(10000, 1000).astype('i') 12 13 start = t.time() 14 test = cy.test_20190524(a, b, c, x, y) 15 print('time : ' + str(round((t.time() - start),5)) + ' [sec]') 16 17if __name__ == "__main__": 18 main()
setup.py
Python
1from distutils.core import setup 2from distutils.extension import Extension 3from Cython.Distutils import build_ext 4 5setup( 6 cmdclass = {'build_ext': build_ext}, 7 ext_modules = [Extension("test_20190524", ["test_20190524.pyx"])] 8)
回答2件
あなたの回答
tips
プレビュー