2008-08-27 10 views
73

私は、スレッドがPythonでどのように動作するかについて頭を落とそうとしていましたが、動作方法に関する良い情報を見つけるのは難しいです。私はちょうどリンクか何かを見逃しているかもしれないが、公式のドキュメンテーションが主題に関して非常に徹底していないようであり、私は良い執筆を見つけることができなかった。スレッドはPythonでどのように機能し、Pythonスレッドの一般的な落とし穴は何ですか?

私が知る限り、スレッドは一度に1つしか実行できません。アクティブなスレッドは10命令ごとに切り替わります。

ここには良い説明がありますか、それとも提供することができますか?また、Pythonでスレッドを使用している間に実行する一般的な問題を認識することは非常にうれしいでしょう。

答えて

46

はい、そこだけすることができます:あなたがに見なければならないいくつかのフレームワークもあります一度に1つのスレッドを実行します。ここでは、このについてのいくつかの洞察力を持ついくつかのリンクは以下のとおりです。最後のリンクから

興味深い引用:

は、私はそれが何を意味するのか、すべてを説明してみましょう。 スレッドは同じ仮想マシン 内で実行されるため、同じ 物理マシンで実行されます。プロセスは同じ物理マシン上で を実行したり、別の物理マシン上で実行したりすることができます。 スレッドの周りにアプリケーションを設計する場合、 複数のマシンにアクセスするために何もしていません。したがって、 を、多くのコアが単一の マシン(多くの場合、 になります)にスケーリングできますが、実際には のスケールに達するには、とにかく 複数のマシンの問題を解決する必要があります。

マルチコアを使用する場合、pyprocessingは、実際の並列化を行うプロセスベースのAPIを定義しています。 PEPには、いくつかの興味深いベンチマークも含まれています。

+1

本当にsmoothspanの引用文にコメントがあります。確かにPythonのスレッディングはマシンに複数のものがあっても1つのコアに制限されますか?コンテキストスイッチなしで次のスレッドを実行できるようになるため、マルチコアの利点があるかもしれませんが、Pythonスレッドは決して> 1コアを使用することはできません。 –

+2

CモジュールがGILとうまくやり取りして、それ自身のネイティブスレッドを実行していない限り、Pythonスレッドは実際には1つのコアに限定されています。 – Arafangion

+0

実際には、複数のコアがスレッドを無駄にすることはありません。なぜなら、各スレッドがGILにアクセスできるかどうかを確認することが多いためです。新しいGILでもパフォーマンスはさらに悪化しています... http://www.dabeaz.com/python/NewGIL.pdf – Basic

18

以下は、基本的なスレッドのサンプルです。 20スレッドを生成します。各スレッドはスレッド番号を出力します。それを実行し、印刷順序を観察します。

import threading 
class Foo (threading.Thread): 
    def __init__(self,x): 
     self.__x = x 
     threading.Thread.__init__(self) 
    def run (self): 
      print str(self.__x) 

for x in xrange(20): 
    Foo(x).start() 

Pythonスレッドのヒントとして、タイムスライスが実装されています。これは彼らが "平行"効果を得る方法です。

私の例では、私のFooクラスはスレッドを拡張し、runメソッドを実装しています。これは、スレッドで実行したいコードがどこに行くかです。スレッドを開始するには、runメソッドを自動的に呼び出すスレッドオブジェクトのstart()を呼び出します。

もちろん、これは基本的なものです。最終的には、スレッドの同期やメッセージの受け渡しのためのセマフォ、mutex、ロックについて学びたいと思うでしょう。

34

Pythonはかなり簡単にスレッドすることができますが、警告があります。あなたが知る必要がある最大のものは、グローバルインタープリタロックです。これにより、1つのスレッドだけがインタプリタにアクセスできます。これは2つのことを意味します.1)Pythonでlock文を使用することはめったにありません。また、マルチプロセッサシステムを利用する場合は、別々のプロセスを使用する必要があります。編集:私はまた、GILを回避する場合は、C/C++でコードのいくつかを置くことができることを指摘する必要があります。

したがって、スレッドを使用する理由を再検討する必要があります。デュアルコアアーキテクチャを活用するためにアプリケーションを並列化するには、アプリを複数のプロセスに分割する必要があります。

応答性を向上させたい場合は、スレッドを使用することを検討する必要があります。しかし、他の選択肢、すなわちmicrothreadingがあります。なぜならグローバルインタープリタロック(GIL)の

+0

@JS - 固定。とにかくそのリストは時代遅れだった。 –

+0

マルチコアシステムを活用するために必要な複数のプロセス(すべてのオーバーヘッドが伴う)が必要なことは間違っています。 32個の論理コアを持つサーバーがいくつかあります。効率的に使用するには32個のプロセスが必要です。狂気 – Basic

+0

@Basic - 最近スレッドを開始してからプロセスを開始するまでのオーバーヘッドは最小限に抑えられます。私たちが毎秒何千ものクエリを話していると問題が起きるかもしれませんが、まずは忙しいサービスのためにPythonの選択に疑問を呈します。 –

9

個々のワーカーがI/Oバインド操作を行っている場合は、Pythonでスレッドを使用します。あなたがマシン上の複数のコアにまたがって拡大しようとしている場合は、Python用の良いIPCフレームワークを見つけるか、別の言語を選んでください。

1

GILは、複数のタスクの外観を表示するために頻繁にポーリングするように設定されていることを覚えておいてください。この設定はきめ細かく調整できますが、スレッドがやっている作業やコンテキストスイッチの多くが問題を引き起こすはずであるという提案をしています。

私はこれまで、プロセッサ上の複数の親を示唆し、同じコアにジョブを維持しようとしました。

2

GILの簡単な解決策は、multiprocessingモジュールです。これは、スレッドモジュールの代わりにドロップとして使用できますが、スレッドの代わりに複数のインタープリタプロセスを使用します。このため、簡単な処理のための単純なスレッド化よりもオーバーヘッドが少しありますが、必要に応じて実際の並列化の利点が得られます。 また、複数の物理マシンに容易に拡張できます。

本当に大規模な並列化が必要な場合、私はさらに見ていきますが、より包括的なフレームワークを実装するためのすべての作業を行わずに、1つのコンピュータまたはすべてのコアのすべてのコアに拡張したい場合は、これはあなたのです。