前提・実現したいこと
Python3にてプログラムをつくっております。処理高速化を実現したいです。
numpyを使用していますが、ループ回数が膨大なので遅いです。
下記サンプルコードは、私の環境では0.45秒です。
これでも十分速いのかもしれませんが、あと10倍以上は速くしたいです。
良いアドバイスはありますでしょうか?
ソースコード例
python
1import numpy as np 2import time as t 3 4start = t.time() 5sl = np.random.rand(10000) 6ang = np.random.rand(10000) 7 8def main(): 9 10 n = sl.size 11 msk = np.ones(n) 12 angmax = ang[0] 13 14 for i in range(1, n): 15 #maxidx = np.argmax([angmax, ang[i]]) 16 #angmax = np.max([angmax, ang[i]]) 17 #if maxidx == 0: msk[i] = 1 18 if angmax > ang[i]: 19 msk[i] = 3 20 else: 21 angmax = ang[i] 22 23 csl = sl[0:i+1] 24 ply = np.where(csl > sl[i]) 25 kly = np.size(ply) 26 if kly > 0: msk[ply] = 2 27 28 print(msk) 29 print('time : ' + str(round((t.time() - start),3)) + ' [sec]') 30 31if __name__ == "__main__": 32 main()
試したこと
Cythonは試してみましたが殆ど速くなりませんでした(要検証)。
jitも試しましたが速くなりませんでした。
for文を除いてOpenCVで書ければ速くなりそうですが、
具体的な記述方法がわからない状況です。
Cython
1import cython 2import numpy as np 3cimport numpy as np 4 5sl = np.random.rand(10000) 6ang = np.random.rand(10000) 7 8cdef int n = sl.size 9cdef np.ndarray msk = np.ones(n) 10cdef float angmax = ang[0] 11 12for i in range(1, n): 13 if angmax > ang[i]: 14 msk[i] = 3 15 else: 16 angmax = ang[i] 17 18 csl = sl[0:i+1] 19 ply = np.where(csl > sl[i]) 20 kly = np.size(ply) 21 if kly > 0: msk[ply] = 2
補足情報
GPUマシンはありますので、例えばcupyを使用して速くなるのであれば試してみたいです。
もしcupyでの記述方法がわかればご教授頂けると幸いです。
質問欄のコードの記述は markdown を使いましょう。
ありがとうございます。すぐに気づいたので修正しております。
angmax = np.max([angmax, ang[i]])
これは何のためにここにあるのでしょうか。必要なく最大値の計算を繰り返しているように見えるのですが。
ひとつ前の配列要素と大小比較しているだけですので、np.maxを使う必要はないですね。すみません、実は気づいていましたがnumpyは速い(はず)なのでそのまま修正せずにいました。修正して速度をみてみます。
アルゴリズムの説明があるとなおいいですね。
元のやりたい処理を数式もしくは言葉で書いていただかないと、コード化した段階ですでに冗長になっている可能性があるので、改善の余地がないかどうかわからないですね。
ありがとうございます。処理の説明ですが、実は、元は別の方がIDLで書かれているのをそのままPythonで実装しなおしただけですので、私も現在ソースと睨めっこ中です。IDLで実装した人もこれで正しいのかわからないという状況のようです。説明ができそうであれば、可能な範囲で、回答させて頂く予定です(業務機密にひっかからない程度に)。少し時間かかるかもしれません。なお、非常に簡単に説明すると、衛星画像の影やレイオーバのサンプルコードです。かなり加工し、かつコメントは全て消しているので、なんのコードかわからないですよね。。すみません。
処理の概要が記載できないのであれば、KojiDoi さんが指摘されているような 「argmax() と max() をしているのは、計算量2倍なので冗長」というような指摘しかできないですね。
> Cで書いても速くならないと考えられます。
そんなことはないと思いますよ。
コンパイラの最適化も効きますし、for 文を使うようなアルゴリズムであれば、numpy も中身は C とはいえいろいろオーバーヘッドがあるので、C/C++ でアルゴリズムを書いたほうが全然早いです。
きちんとコードを書けば、Python の10倍ぐらい早くすることは全然可能です。
ご指摘いただいた「argmax() と max()」の部分を修正しました。
0.2秒速くなりました。ありがとうございます。
また、Cでも書いて速度確認してみます。最近定時退社が厳しいので明日回答いたします。
ロジックの変更およびCythonにて約1万倍の高速化を実現できました!
変更なし:0.65秒
部分ロジック変更(python):0.45秒
全般ロジック変更(python):0.06秒
全般ロジック変更(Cython):0.00006秒
本当にありがとうございます!みなさんにベストアンサー付けたいところですが申し訳ないです。
回答1件
あなたの回答
tips
プレビュー