0

Python でスクリプトを作成しましたが、最後まで実行するのに 20 時間以上かかります。

私のコードはかなり大きいので、簡略化したものを投稿します。

コードの最初の部分:

flag = 1
mydic = {}
for i in mylist:
    mydic[flag] = myfunction(i)
    flag += 1

mylistには 700 を超えるエントリがあり、呼び出すたびmyfunctionに約 20 秒間実行されます。

そこで、並列プログラミングを使用して反復を 2 つのグループに分割し、同時に実行できないかと考えていました。それは可能で、以前よりもハーフタイムが必要ですか?

コードの 2 番目の部分:

mymatrix = []
for n1 in range(0,flag):
    mat = []
    for n2 in range(0,flag):
        if n1 >= n2:
            mat.append(0)
        else:
            res = myfunction2(mydic(n1),mydic(n2))
            mat.append(res)
    mymatrix.append(mat)

したがって、mylist700 のエントリがある場合、上三角行列である 700x700 の行列を作成したいと思います。しかし、myfunction2()毎回約30秒必要です。ここでも並列プログラミングを使用できるかどうかわかりません。

myfunction()andmyfunction2()は、外部 API を呼び出して結果を返す関数であるため、簡略化できません。

より速くするために変更する方法について何か提案はありますか。

4

2 に答える 2

1

あなたのコメントに基づいて、30 秒の時間は主に外部 API 呼び出しによるものである可能性が非常に高いと思います。コードのどの部分が実際に速度低下の原因であるかをテストするために、いくつかのタイミング コードを追加します。

外部 API 呼び出しによるものである場合は、簡単な修正方法がいくつかあります。外部 API 呼び出しはブロックされるため、並列モデルに移行できればスピードアップが得られます (ただし、30 秒のブロックは私には巨大に聞こえます)。

2 つのループの出力を関数に渡す引数の行列にすることで、簡単な「タスク リスト」を作成するのが最も簡単だと思います。次に、それらをパイプしてCeleryタスクを実行します。これにより、最小限の作業でかなりのスピードアップが得られるはずです。

threadingまたはmultiprocessingモジュールを使用してタスク (またはセクション) を実行したり、Python ですべてを記述したりすることで、おそらくより多くの時間を節約できますTwistedが、通常は単純なセロリ関数よりも時間がかかります。

このアプローチの 1 つの注意点はCelery、大量の作業をディスパッチすることになるため、結果をポーリングする機能が必要になることです。これは、セロリがすべてのタスクの結果を得るまで繰り返されるwhileループである可能性があります。sleeps(10)で実行するとTwisted、終了時に結果にアクセス/追跡できます。マルチプロセッシングでこのようなことをする必要がなかったので、それがどのように適合するかわかりません.

于 2013-09-15T16:22:08.990 に答える
0

forループの1つの代わりに、2番目の部分にジェネレーターを使用するのはどうですか

def fn():
    for n1 in range(0, flag):
        yield n1

generate = fn()

while True:
    a = next(generate)
    for n2 in range(0, flag):
        if a >= n2:
            mat.append(0)
        else:
            mat.append(myfunction2(mydic(a),mydic(n2))
            mymatrix.append(mat)
于 2013-09-15T15:52:57.290 に答える