5

私は自分のコードのスループットが非常に重要なプロジェクトに取り組んでおり、いくつかの検討の結果、プログラムをスレッド化することを選択しました。

メインスレッドとサブスレッドは両方とも、2つの共有辞書を追加および削除します。Pythonでのロックのパフォーマンス、遅い操作などを考慮して、いくつかの入力についてインターウェブを調べてきました。

したがって、Pythonは実際にはまったくスレッド化されていないので(GILは1つのコアでのみ機能すると考えて)、アプリケーションで高いパフォーマンスが必要な場合は、IOの処理以外にスレッド化することで勝つことができますか? ?

編集

実際の質問は(洞察に満ちたコメントの後)です

GILがあるので、マルチスレッドはPythonで意味がありますか?

4

2 に答える 2

16

IMO、ロックソリューションは、主に複数のスレッドが実際にそれを待っているときに、パフォーマンスに大きな影響を与えます。

競合のないロックを取得して解放するコストは、取るに足らないものでなければなりません。

このスレッドは、それに関するテストを示しています。

わかりました。Python3.2を使用したLinuxでの競合のないロックの取得と解放のコストは次のとおりです。

$ python3 -m timeit \
  -s "from threading import Lock; l=Lock(); a=l.acquire; r=l.release" \
  "a(); r()"

10000000 loops, best of 3: 0.127 usec per loop

そして、ダミーのPython関数を呼び出すコストは次のとおりです。

$ python3 -m timeit -s "def a(): pass" "a(); a()"

1000000 loops, best of 3: 0.221 usec per loop

そして、これが些細なC関数(Falseシングルトンを返す)を呼び出すコストです。

$ python3 -m timeit -s "a=bool" "a(); a()"

10000000 loops, best of 3: 0.164 usec per loop

また、ロックをコンテキストマネージャーとして使用すると、想像するほど速くはなく、実際には遅くなることに注意してください。

$ python3 -m timeit -s "from threading import Lock; l=Lock()" \
  "with l: pass"

1000000 loops, best of 3: 0.242 usec per loop

少なくともLinuxでは、控えめに言っても、ロックのパフォーマンスを改善する余地はあまりないようです。

PS:RLockはLockと同じくらい高速になりました:

$ python3 -m timeit \
  -s "from threading import RLock; l=RLock(); a=l.acquire; r=l.release" \
  "a(); r()"

10000000 loops, best of 3: 0.114 usec per loop
于 2015-05-08T03:17:27.777 に答える
6

まず第一に、どの言語でもロックすることはパフォーマンスのボトルネックです。可能な場合はロックを最小限に抑えます。たとえば、共有ディレクトリを使用しないでください。代わりにツリーを作成し、各スレッドをそのツリーの異なるブランチで機能させます。

多くのI/Oを実行するため、パフォーマンスの問題はそこにあり、スレッド化によって必ずしも問題が改善されるとは限りません。最初にイベント駆動型アーキテクチャを調べます。

ここでは、GILが問題になる可能性は低いです。たとえば、スレッドがCコードを入力するたびに解放されます(ほぼ確実にI / O呼び出し中)。ボトルネックになった場合、複数のプロセスに移動してください。たとえば、私が管理している大規模なイントラネットクラスターでは、2つのスレッドごとに6つのプロセスを実行して、すべてのCPUコアを最大限に活用します(2つのプロセスの負荷は非常に軽いです)。

複数のプロセスが必要な場合は、multiprocessingモジュールを使用するか、サーバーの複数のインスタンス(それぞれが異なるポートでリッスンしている)を簡単に起動し、haproxyなどのロードバランサーを使用してトラフィックを各サーバーに転送します。

于 2012-08-15T09:03:24.573 に答える