7

私はPython2.7を使用してgaeでアプリを開発していましたが、ajax呼び出しはAPIからいくつかのデータを要求し、1回の要求には最大200ミリ秒かかる可能性がありますが、2つのブラウザーを開いて、非常に近い時間に2つの要求を行うと、その2倍、すべてをスレッドに入れようとしましたが、機能しませんでした。(これは、開発サーバーだけでなく、アプリがオンラインの場合に発生します)

だから私はこれが一般的にPythonの問題であるかどうかを確認するためにこの簡単なテストを書きました(ビジーウェイトの場合)、ここにコードと結果があります:

def work():
    t = datetime.now()
    print threading.currentThread(), t
    i = 0
    while i < 100000000:
        i+=1
    t2 = datetime.now()
    print threading.currentThread(), t2, t2-t

if __name__ == '__main__': 
    print "single threaded:"
    t1 = threading.Thread(target=work)
    t1.start()
    t1.join()

    print "multi threaded:"
    t1 = threading.Thread(target=work)
    t1.start()
    t2 = threading.Thread(target=work)
    t2.start()
    t1.join()
    t2.join()

mac os x、core i7(4コア、8スレッド)、python2.7での結果:

single threaded:
<Thread(Thread-1, started 4315942912)> 2011-12-06 15:38:07.763146
<Thread(Thread-1, started 4315942912)> 2011-12-06 15:38:13.091614 0:00:05.328468

multi threaded:
<Thread(Thread-2, started 4315942912)> 2011-12-06 15:38:13.091952
<Thread(Thread-3, started 4323282944)> 2011-12-06 15:38:13.102250
<Thread(Thread-3, started 4323282944)> 2011-12-06 15:38:29.221050 0:00:16.118800
<Thread(Thread-2, started 4315942912)> 2011-12-06 15:38:29.237512 0:00:16.145560

これはかなり衝撃的です!1つのスレッドでこれを行うのに5秒かかる場合、2つのスレッドを同時に開始すると、両方のタスクを完了するのに同じ時間がかかると思いましたが、ほぼ3倍の時間がかかります。これにより、スレッドのアイデア全体が役に立たなくなります。それらを順番に実行する方が高速です。

ここで何が欠けていますか。

4

3 に答える 3

9

David Beazley はPyCon 2010 でこの問題について講演しました。他の人が既に述べたように、タスクによっては、特に複数のコアでスレッド化を使用すると、単一のスレッドで実行される同じタスクよりもパフォーマンスが低下する可能性があります。Beazley が発見した問題は、 「GIL バトル」を持つ複数のコアに関係していました。

ここに画像の説明を入力

GIL の競合を避けるために、タスクを別々のスレッドではなく別々のプロセスで実行すると、より良い結果が得られる場合があります。マルチプロセッシングモジュールは、特にマルチプロセッシング API がスレッド API に非常に似ているため、これを行うための便利な方法を提供します。

import multiprocessing as mp
import datetime as dt
def work():
    t = dt.datetime.now()
    print mp.current_process().name, t
    i = 0
    while i < 100000000:
        i+=1
    t2 = dt.datetime.now()
    print mp.current_process().name, t2, t2-t

if __name__ == '__main__': 
    print "single process:"
    t1 = mp.Process(target=work)
    t1.start()
    t1.join()

    print "multi process:"
    t1 = mp.Process(target=work)
    t1.start()
    t2 = mp.Process(target=work)
    t2.start()
    t1.join()
    t2.join()

収量

single process:
Process-1 2011-12-06 12:34:20.611526
Process-1 2011-12-06 12:34:28.494831 0:00:07.883305
multi process:
Process-3 2011-12-06 12:34:28.497895
Process-2 2011-12-06 12:34:28.503433
Process-2 2011-12-06 12:34:36.458354 0:00:07.954921
Process-3 2011-12-06 12:34:36.546656 0:00:08.048761

PS。zeekay がコメントで指摘したように、GIL の戦いは CPU バウンドのタスクに対してのみ厳しいものです。IO バウンドのタスクでは問題になりません。

于 2011-12-06T17:22:48.417 に答える
4

CPython インタープリターは複数のスレッドの実行を許可しません。GIL http://wiki.python.org/moin/GlobalInterpreterLockについて読む

そのため、スレッドを使用する CPython では、特定のタスクを効率的な方法で同時に実行することはできません。

GAE で並列処理を行いたい場合は、別々のリクエストで並列処理を開始します。

また、Python 並列 wiki http://wiki.python.org/moin/ParallelProcessingを参照することもできます。

于 2011-12-06T17:09:34.100 に答える
1

私は時間がどこに向かっているのかを見ていきます。たとえば、サーバーが 200 ミリ秒ごとに 1 つのクエリしか応答できないとします。サーバーが提供できるのはそれだけであるため、200ミリ秒ごとに1つの応答しか得られません。

于 2011-12-06T17:09:54.157 に答える