3

1000x1000 の大きさの 2 つの配列を反復処理する必要があります。反復を高速化するために解像度を 100x100 に下げましたが、それでも 1 つの配列で約 15 分かかります。そのため、両方を同時に反復しようとしたところ、次のことがわかりました。

for index, (x,y) in ndenumerate(izip(x_array,y_array)):

しかし、その後エラーが発生します:

ValueError: too many values to unpack

ここに私の完全なpythonコードがあります:これは私の修士論文のためのものであり、最終的に約100回実行する必要があるため、これをより速くするのを手伝ってくれることを願っています...

area_length=11
d_circle=(area_length-1)/2

xdis_new=xdis.copy()
ydis_new=ydis.copy()
ie,je=xdis_new.shape


while (np.isnan(np.sum(xdis_new))) and (np.isnan(np.sum(ydis_new))):
xdis_interpolated=xdis_new.copy()
ydis_interpolated=ydis_new.copy()
# itx=np.nditer(xdis_new,flags=['multi_index'])
# for x in itx:
    # print 'next x and y'
for index, (x,y) in ndenumerate(izip(xdis_new,ydis_new)):
    if np.isnan(x):
        print 'index',index[0],index[1]
        print 'interpolate'
        # define indizes of interpolation area
        i1=index[0]-(area_length-1)/2
        if i1<0:
            i1=0
        i2=index[0]+((area_length+1)/2)
        if i2>ie:
            i2=ie
        j1=index[1]-(area_length-1)/2
        if j1<0:
            j1=0
        j2=index[1]+((area_length+1)/2)
        if j2>je:
            j2=je
        # -->
        print 'i1',i1,'','i2',i2
        print 'j1',j1,'','j2',j2

        area_values=xdis_new[i1:i2,j1:j2]
        print area_values

        b=area_values[~np.isnan(area_values)]

        if len(b)>=((area_length-1)/2)*4:

            xi,yi=meshgrid(arange(len(area_values[0,:])),arange(len(area_values[:,0])))

            weight=zeros((len(area_values[0,:]),len(area_values[:,0])))
            d=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weight_fac=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weighted_area=zeros((len(area_values[0,:]),len(area_values[:,0])))

            d=sqrt((xi-xi[(area_length-1)/2,(area_length-1)/2])*(xi-xi[(area_length-1)/2,(area_length-1)/2])+(yi-yi[(area_length-1)/2,(area_length-1)/2])*(yi-yi[(area_length-1)/2,(area_length-1)/2]))
            weight=1/d
            weight[where(d==0)]=0
            weight[where(d>d_circle)]=0
            weight[where(np.isnan(area_values))]=0

            weight_sum=np.sum(weight.flatten())
            weight_fac=weight/weight_sum
            weighted_area=area_values*weight_fac

            print 'weight'
            print weight_fac
            print 'values'
            print area_values
            print 'weighted'
            print weighted_area

            m=nansum(weighted_area)
            xdis_interpolated[index]=m
            print 'm',m

        else:
            print 'insufficient elements'

    if np.isnan(y):
        print 'index',index[0],index[1]
        print 'interpolate'
        # define indizes of interpolation area
        i1=index[0]-(area_length-1)/2
        if i1<0:
            i1=0
        i2=index[0]+((area_length+1)/2)
        if i2>ie:
            i2=ie
        j1=index[1]-(area_length-1)/2
        if j1<0:
            j1=0
        j2=index[1]+((area_length+1)/2)
        if j2>je:
            j2=je
        # -->
        print 'i1',i1,'','i2',i2
        print 'j1',j1,'','j2',j2

        area_values=ydis_new[i1:i2,j1:j2]
        print area_values

        b=area_values[~np.isnan(area_values)]

        if len(b)>=((area_length-1)/2)*4:

            xi,yi=meshgrid(arange(len(area_values[0,:])),arange(len(area_values[:,0])))

            weight=zeros((len(area_values[0,:]),len(area_values[:,0])))
            d=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weight_fac=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weighted_area=zeros((len(area_values[0,:]),len(area_values[:,0])))

            d=sqrt((xi-xi[(area_length-1)/2,(area_length-1)/2])*(xi-xi[(area_length-1)/2,(area_length-1)/2])+(yi-yi[(area_length-1)/2,(area_length-1)/2])*(yi-yi[(area_length-1)/2,(area_length-1)/2]))
            weight=1/d
            weight[where(d==0)]=0
            weight[where(d>d_circle)]=0
            weight[where(np.isnan(area_values))]=0

            weight_sum=np.sum(weight.flatten())
            weight_fac=weight/weight_sum
            weighted_area=area_values*weight_fac

            print 'weight'
            print weight_fac
            print 'values'
            print area_values
            print 'weighted'
            print weighted_area

            m=nansum(weighted_area)
            ydis_interpolated[index]=m
            print 'm',m

        else:
            print 'insufficient elements'

    else:
        print 'no need to interpolate'

xdis_new=xdis_interpolated
ydis_new=ydis_interpolated
4

5 に答える 5

2

いくつかのアドバイス:

  • コードをプロファイリングして、最も遅い部分を確認します。反復ではなく、毎回実行する必要がある計算かもしれません。
  • 関数呼び出しをできるだけ減らします。関数呼び出しは、Python では無料ではありません。
  • 最も遅い部分を C 拡張として書き直してから、Python コードでその C 関数を呼び出します ( Python インタープリターの拡張と埋め込みを参照してください)。
  • このページにもいくつかの良いアドバイスがあります。
于 2012-08-14T08:43:06.133 に答える
1

forこれをループとして使用できます。

for index, x in ndenumerate((x_array,y_array)):

しかし、コンピューターは同時に 2 つのことを行うことができないため、あまり役に立ちません。

于 2012-08-14T09:02:20.733 に答える
1

単一のループで 2 つの配列を反復処理することを具体的に要求しました。ここにそれを行う方法があります

l1 = ["abc", "def", "hi"]
l2 = ["ghi", "jkl", "lst"]
for f,s in zip(l1,l2):
    print "%s : %s" %(f,s)

上記は python 3 用です。python 2 には izip を使用できます。

于 2012-08-14T09:11:31.700 に答える
0

ndenumerateコメント #1: イテレータで使用したくないのizipは、イテレータが出力されるためです。これは、必要なものではありません。

コメント #2:

i1=index[0]-(area_length-1)/2
if i1<0:
    i1=0

で簡略化でき、特定の変数にi1 = min(index[0]-(area_length-1)/2, 0)保存できます。(area_length+/-1)/2

アイデア#1:配列のフラットバージョンで反復してみてください。つまり、次のようなものを使用して

for (i, (x, y)) in enumerate(izip(xdis_new.flat,ydis_new.flat)): 

divmod(i, xdis_new.shape[-1])最初に行ごとに反復する必要があるため、 を介して元のインデックスを取得できます。

アイデア #2: のみを反復処理しnansます。つまり、配列を でインデックス付けするとnp.isnan(xdis_new)|np.isnan(ydis_new)、反復回数を節約できます。

編集#1

  • を個別に計算するため、ループ内dweight_facおよびを初期化する必要はおそらくありません。weighted_area

  • あなたweight[where(d>0)]はで簡素化することができますweight[d>0]

  • 必要weight_facですか?計算weightしてその場で正規化することはできませんか? これにより、一時的な配列が節約されます。

于 2012-08-14T09:00:53.597 に答える
0

プロファイリングは、費やされたすべての時間が実際にどこに費やされているかを特定するための良い出発点です。

cProfile必要なオーバーヘッドが最小限で、十分な情報が得られるため、通常はこのモジュールを使用します。

import cProfile
import pstats
cProfile.run('main()', "ProfileData.txt", 'tottime')
p = pstats.Stats('ProfileData.txt')   
p.sort_stats('cumulative').print_stats(100)

あなたの例main()では、ファイルの最後でこのコード スニペットを使用できるようにするには、コードを関数にラップする必要があります。

于 2012-08-14T09:09:17.930 に答える