0

繰り返しますが、大きなループに関する質問があります。

関数があるとします

limits

def limits(a,b):
  *evaluate integral with upper and lower limits a and b*
  return float result

A と B は、値 a と b を格納する単純な np.arrays です。ここで、A と B の長さがそれぞれ 300'000 であり、積分が対称であるため、積分を 300'000^2/2 回計算したいと考えています。

Python では、A と B の組み合わせを作成してから積分に入れるなど、いくつかの方法を試しitertools.combinations_with_replacementましたが、それには膨大な時間がかかり、メモリが完全に過負荷になります。たとえば、ループを別の言語に転送して、これを高速化する方法はありますか?

ループを実行したい

for i in range(len(A)):
  for j in range(len(B)):
    np.histogram(limits(A[i],B[j]))

limits正方形に成長する追加の配列を格納しないために、戻り値のヒストグラムを作成することが望ましいと思います。

私が読んだことから、pythonはこの反復的な分析に最適な選択ではありません。

したがって、このループを Python 内の別の言語で評価することは合理的でしょうか? はいの場合、その方法。コードを転送する方法があることは知っていますが、これまで行ったことはありません。

ご協力いただきありがとうございます。

4

1 に答える 1

0

メモリ フットプリントが心配な場合は、for ループに入るときに結果をビンに入れるだけです。

num_bins = 100
bin_upper_limits = np.linspace(-456, 456, num=num_bins-1)
# (last bin has no upper limit, it goes from 456 to infinity)
bin_count = np.zeros(num_bins)
for a in A:
    for b in B:
        if b<a:
             # you said the integral is symmetric, so we can skip these, right?
             continue
        new_result = limits(a,b)
        which_bin = np.digitize([new_result], bin_upper_limits)
        bin_count[which_bin] += 1

したがって、大きなものはメモリに保存されません。

速度に関しては、圧倒的に多くの時間が評価に費やされていると思いlimits(a,b)ます。この場合、ループとビニングは非常に高速です。Python でも同様です。これを確信するには、行new_result = limits(a,b)をに置き換えてみてくださいnew_result = 234。ループが非常に高速に実行されることがわかります。(私のコンピューターでは数分で、引用した4時間の数字よりもはるかに短いです。)PythonはCに比べてそれほど速くループしませんが、この場合は問題になりません。

呼び出しを高速化するために何をしてもlimits()(別の言語での実装を含む)、プログラムが高速化されます。

アルゴリズムを変更すると、改善の余地が大いにあります。あなたがしているように見えることの例を見てみましょう。A と B が 0,1,2,3 だとしましょう。0-->0、0-->1、1-->1、1-->2、0-->2 などの範囲で関数を統合しています。何度も同じ作業。0-->1 と 1-->2 を積分した場合、これら 2 つの結果を合計して積分 0-->2 を得ることができます。手の込んだ積分アルゴリズムを使用する必要はありません。既に知っている 2 つの数値を追加するだけで済みます。

したがって、すべての最小範囲 (0-->1、1-->2、2-->3) で積分を計算し、結果を配列に格納し、結果のサブセットを追加して取得できるように思えます任意の範囲の積分。このプログラムを 4 時間ではなく数分で実行したい場合は、それらの線に沿って別のアルゴリズムを検討することをお勧めします。

(あなたが解決しようとしている問題を誤解している場合は申し訳ありません。)

于 2013-01-04T16:19:35.070 に答える