19

Pythonを使用して畳み込みのパフォーマンスを向上させたいと考えており、パフォーマンスを向上させる最善の方法についての洞察を望んでいました。

私は現在、以下のスニペットのようなコードを使用して、scipy を使用して畳み込みを実行しています。

import numpy
import scipy
import scipy.signal
import timeit

a=numpy.array ( [ range(1000000) ] )
a.reshape(1000,1000)
filt=numpy.array( [ [ 1, 1, 1 ], [1, -8, 1], [1,1,1] ] )

def convolve():
  global a, filt
  scipy.signal.convolve2d ( a, filt, mode="same" )

t=timeit.Timer("convolve()", "from __main__ import convolve")
print "%.2f sec/pass" % (10 * t.timeit(number=10)/100)

グレースケール (0 ~ 255 の整数値) を使用して画像データを処理していますが、現在、畳み込みあたり約 4 分の 1 秒を取得しています。私の考えは、次のいずれかを行うことでした。

できればいくつかの最適化を行って、corepy を使用してください。icc と iml で numpy を再コンパイルします。python-cuda を使用します。

誰かがこれらのアプローチのいずれかを経験したことがあるかどうか(どのような種類のゲインが典型的であるか、そしてそれが時間の価値があるかどうか)、またはNumpyで畳み込みを実行するためのより良いライブラリを誰かが知っているかどうか疑問に思っていました.

ありがとう!

編集:

Numpy を使用して C で python ループを書き直すことにより、約 10 倍高速化します。

4

5 に答える 5

10

2D畳み込みを行うためのscipyのコードは、少し面倒で最適化されていません。scipyの低レベルの機能を垣間見たい場合は、http://svn.scipy.org/svn/scipy/trunk/scipy/signal/firfilter.cを参照してください。

示したような小さくて一定のカーネルで処理するだけの場合は、次のような関数が機能する可能性があります。

def specialconvolve(a):
    # sorry, you must pad the input yourself
    rowconvol = a[1:-1,:] + a[:-2,:] + a[2:,:]
    colconvol = rowconvol[:,1:-1] + rowconvol[:,:-2] + rowconvol[:,2:] - 9*a[1:-1,1:-1]
    return colconvol

この関数は、上記で提案したDarenWのようなカーネルの分離可能性を利用するだけでなく、より最適化されたnumpy算術ルーチンを利用します。私の測定では、convolve2d関数よりも1000倍以上高速です。

于 2010-02-05T04:42:23.583 に答える
1

ctypes で C と言う前に、C でスタンドアロンの畳み込みを実行して、限界がどこにあるかを確認することをお勧めします。
同様に、CUDA、cython、scipy.weave ...

7feb を追加: クリッピングを伴う convolve33 8 ビット データは、gcc 4.2 を使用した私の mac g4 pcc で、ポイントごとに ~ 20 クロック サイクル、メモリ アクセスごとに 2 クロック サイクルかかります。あなたの走行距離異なります。

いくつかの微妙な点:

  • 0..255 への正しいクリッピングを気にしますか? np.clip() は遅い、cython などはわかりません。
  • Numpy/scipy は、一時的に A のサイズのメモリを必要とする場合があります (したがって、2*sizeof(A) < キャッシュ サイズを維持してください)。
    ただし、C コードが実行中の更新をインプレースで実行する場合、それはメモリの半分ですが、アルゴリズムは異なります。

ところで、google theano convolve => 「scipy.signal.convolve2d を模倣する必要がある畳み込み演算ですが、より高速です!開発中です」

于 2010-02-05T18:30:04.063 に答える
0

畳み込みの典型的な最適化は、信号の FFT を使用することです。その理由は、実空間での畳み込みは FFT 空間での積だからです。通常の方法でたたみ込みを行うよりも、FFT を計算してから積を計算し、結果の iFFT を計算する方が速いことがよくあります。

于 2010-02-04T01:18:44.563 に答える