2

np.apply_over_axispython-wayにはボトルネックがあり、処理が遅くなるため、Numpy配列を反復処理するための実行可能な代替手段であることが私の理解でした。ただし、反復には約9%の時間がかかるようapply_over_axisです。この前の投稿に便乗して、私は自分のために簡単なタイミングをとることに決めました:

import numpy as np
import timeit

def triv():
     ial = [i for i in xrange(100)]

def super(fluous):
     return fluous

>>> print (timeit.timeit("triv()", setup="from __main__ import triv"))
12.3305490909
>>> print (timeit.timeit("np.apply_along_axis(super, 0, np.arange(100))", setup="from __main__ import np, super"))
130.721563921

なぜそうなのですか?timeit私はその複雑さ(またはそのことについては何でも)を本当によく知りませんが、timeit私の例は十分に単純だと思います。非常に大きな配列の行のデカルト積を反復処理するという私の現実の問題は非常に遅く、進行を妨げるため、誰かが良い回避策を見つけたかどうか疑問に思いました。

前もって感謝します。

4

2 に答える 2

3

そもそも、apply_over_axis1D配列では配列全体が単一の引数として渡されるだけなので、この例は奇妙です。要素ごとに繰り返し呼び出されることはありません。そのためにあなたが欲しいでしょうvectorize

ただし、より一般的には、numpyは任意のPython関数の適用を実際に高速化することはできません。numpyの主な利点は、多くの数学関数の独自の実装を提供し、それらが高速であることです。それは魔法のように機能をとることはできず、ただ速くするだけです。

さらに、あなたの例は完全に平行ではありません。一つには、両方で同じ関数を呼び出しているわけではありません。より具体的には、テストには両方とも、時限テストで入力を作成することが含まれます。つまり、テストの時限部分を作成xrange(100)し、その中に入れます。np.arange(100)したがって、測定していることの一部は、xrangeオブジェクトを作成するよりもNumpy配列を作成する方が遅いということです。

>>> timeit.timeit("np.arange(100)", "import numpy as np")
0.95243776
>>> timeit.timeit("xrange(100)", "import numpy as np")
0.2129926399999995

それはおよそ5倍です。ただし、実際のアプリケーションでは、ほぼ確実に入力配列が作成されているため、これは現実的なテストではありません。

並列テストを使用すると、プレーンリストバージョンの速度は約2倍であることがわかりました。

def doNothing(crud):
    return crud

>>> timeit.timeit("np.vectorize(doNothing)(thing)", "import numpy as np; from __main__ import doNothing; thing = np.arange(100)")
49.13036320000003
>>> timeit.timeit("[doNothing(x) for x in thing]", "import numpy as np; from __main__ import doNothing; thing = np.arange(100)")
25.873566400000072

さらに、適用しているのがnumpy関数である場合、numpyバージョンは大幅に高速になる可能性があります。

>>> timeit.timeit("np.log(thing)", "import numpy as np; import math; from __main__ import doNothing; thing = np.arange(100)+1")
3.2039433600000393
>>> timeit.timeit("[math.log(x) for x in thing]", "import numpy as np; import math; from __main__ import doNothing; thing = np.arange(100)+1")
37.74219519999997

物語の教訓は、numpyは実際にはNUMpyであるということです。これは数値計算を行うために作成されており、それらを高速に実行するための関数を備えています。すべてのループを高速化するだけではありません。任意の関数を適用しているオブジェクトの大きな配列がある場合、numpyがコードを高速化する可能性は低く、速度を低下させる可能性さえあります。(多次元配列への複雑なインデックス付けなどの機能が便利で、ネストされたリストなどを使用する同等のPython構造よりも高速である可能性があるため、数値以外のデータにも非常に役立ちます。ループの高速化には役立ちません。これらの構造。)

于 2013-01-21T07:27:14.847 に答える
1

numpyのインストールディレクトリに移動すると、のpythonコードはnp.apply_along_axisサブ\maディレクトリのファイルにありますextras.py

動作が遅い理由は、選択した軸に沿って配列の1Dスライスに関数を適用するときに、結果を配列に格納し、dtype=objectすべての戻り値を追跡するためdtypesです。処理が完了するとdtype、リスト内で最大のものを選択し、すべてを再キャストしてから返します。これにより、非常に堅牢で非常に低速なコードになります。一般に、numpyのすべての関数型プログラミングルーチンは避けるのが最善です。それらを使用する必要がある場合は、速度がないため、numpyなしで実行することもできます。

これは、標準の迅速で扱いにくい機能では問題に適切に対処できないことを意味するものではありません。質問として投稿してみませんか?

于 2013-01-21T07:39:17.617 に答える