0

私は計算しているスクリプトを持っています:

def sumsquared(arr):
    sum = 0
    idx = 0
    len = arr.__len__()
    while idx < (len - 1):
            sum = sum + (arr[idx] * arr[idx]) + (arr[idx+1] * arr[idx+1])
            idx = idx + 2

    return sum

上記の関数は、2 つのリストを作成し、この関数を 2 回呼び出すループで呼び出されます。1 回目は len ~ 1024 アイテムのリストで、2 回目は len ~ 44100 アイテムのリストです。ループ自体は、入力に応じて 100 ~ 100000 回実行できます。

小さなサイズの入力の場合、cProfileベースのプロファイリングは私に通知します:

ncalls  tottime  percall  cumtime  percall  filename:lineno(function)
---------------------------------------------------------------------
 2560   12.065   0.005    12.065    0.005    beat.py:8(sumsquared)

これは、スクリプトの合計実行時間の約 95% です。関数を高速化する方法はありますか?

4

4 に答える 4

5

あなたの機能は非常に奇妙です。要素の二乗和を計算するだけですが、要素の数が奇数の場合は最後の要素を破棄します。何らかの理由で一度に 2 つ追加しますが、最終結果には影響しません。

高速化するには、独自の関数を作成する代わりにnumpyを使用できます。

>>> x = np.array([1, 2, 3, 4, 5])
>>> sumsquared(x)
30
>>> (x[:2*(len(x)//2)]**2).sum()
30

一般に、何千もの数値のリストがある場合、代わりに numpy 配列を使用すると、パフォーマンスが大幅に向上する可能性があります。

于 2012-09-11T04:43:07.090 に答える
3

これはitertools モジュールの仕事のようです:

def sumsquared(arr):
    s = sum(itertools.imap(operator.mul, arr, arr))
    return s - arr[-1] ** 2 if len(arr) & 1 else s

sumoperator、およびitertoolsを使用すると、純粋な Python オーバーヘッドのほとんどすべてが解消されます。

また、sumは、入力が int、float、または 2 つの混合である場合にほぼ C の速度で実行されるように最適化されています。中間の小計ごとに純粋な python オブジェクトを作成することなく、現在の合計を累積できます。

クレジット: 必要に応じて最終平方を差し引くというアイデアについて、Robert King 氏。

もう 1 つ注意してください。高精度を取得する (つまり、精度の損失を最小限に抑える) ことに関心がある場合は、 sumの代わりにmath.fsumを使用することを検討してください。

于 2012-09-11T04:45:22.923 に答える
2

これは私が見つけることができる最速です

from itertools import imap
from operator import mul
def sumsquared(arr):
    return sum(imap(mul, arr, arr))
于 2012-09-11T05:21:06.870 に答える
1
sum([i**2 for i in arr]) - (arr[-1]**2 if len(arr) % 2 else 0)
于 2012-09-11T04:56:06.267 に答える