5

まず、私はUbuntuの質問としてここに投稿するべきかどうかはわかりませんでした。 しかし、私はそれがOSのものよりもPythonの質問のほうが多いと思います。Pythonアプリケーションが 'system'/kernel CPU時間で停止するのはなぜですか?

私のPythonアプリケーションは、64コアAMDサーバのUbuntu上で動作しています。 ​​を介して.soに呼び出すことによって、ネットワーク経由で5 GigEカメラから画像を取得し、処理します。 アプリケーションで頻繁な一時停止が発生し、カメラのフレームが外部カメラライブラリによって削除されることがあります。

これをデバッグするには、一般的なpsutil Pythonパッケージを使用しました。このパッケージでは、別のスレッドで0.2秒ごとにCPU統計をログアウトします。 私はそのスレッドで0.2秒間スリープ状態になり、そのスリープ時間がかなり長くなると、カメラフレームが落とされることもあります。 私は17秒間の休止を見ました! 私の処理の多くは、OpenCVまたはNumpy(いずれもGILをリリースしています)またはアプリケーションの一部でmultiprocessing.Pool の59個のプロセス(これはPython GILを回避するため)です。

私のデバッグログは、一時停止が発生したときに、プロセスの多くのスレッドで非常に高い「システム」(つまりカーネル)CPU時間を示しています。

たとえば、

:私は突然、その後、大きなジャンプ を( 'プロセスの数字はCPU使用率であり、すなわち完全に使用1つのCPUが1になり、123パーセントを示すLinuxの topは1.2になります)、次のようにCPU時間を参照してください(通常は0.2秒ごと)と
Process user | Process system | OS system % | OS idle % 
19.9   | 10.5   | 6   | 74 
5.6   | 2.3   | 4   | 87 
6.8   | 1.7   | 11   | 75 
4.6   | 5.5   | 43   | 52 
0.5   | 26.4   | 4   | 90 

高いプロセスシステムの使用状況と一致する前に、高いOSシステムの使用状況が1行で報告される理由がわかりません。 64コアのうち26.4 = 41%なので2つが一致します。その時点で私のアプリケーションでは、 (OpenCVのcv2.getTickCount()を使用している私のCPUインフォメーションログスレッドによって決定され、Pythonロギング出力のタイムスタンプのジャンプによって決定されます) が発生し、複数のカメラフレームがドロップされていました。

これが起こると、自分のプロセスの各スレッドのCPU情報も記録されました。 上記の例では、25のスレッドは「システム」CPU使用率0.9で実行されていましたが、0.6ではもう少し多く、これは上記の26.4のプロセスの合計と一致しています。 その時点で約183スレッドが実行されていました。

この一時停止は通常、マルチプロセッシングプールが使用された後に発生するようです(短いバーストに使用されます)が、プールが使用されるたびに決して行われません。 また、プールの外で発生する必要がある処理量を半分にすると、カメラスキップは発生しません。

質問:どのようにOSのシステム/カーネルの時間が突然屋根を通過するのかを判断するにはどうすればよいですか?なぜそれがPythonアプリケーションで起こるのでしょうか?

さらに重要なことは、なぜこれが起こっているのか、それを避ける方法ですか?

注:

  • これは、rootとして実行(それは残念ながらカメラライブラリ用に持っている)、カメラが(成り上がりでrespawnを使用して)アプリの再起動をオフにし、これが複数起きているupstart
  • から一日に一度の実行ではないので、これはプロセスが始まるとすぐに起きることがあります。
  • 同じコードが何度も繰り返し実行されています。私のコードの別のブランチを実行しているわけではありません。
  • 現在-2のniceを持って、私はノー影響を及ぼす
  • のUbuntu 12.04.5 LTS
  • のPython 2.7
  • マシンは、私が
+0

プロファイリングでコードの所要時間を確認しましたか? https://docs.python.org/2/library/profile.html – bsa

+0

cProfileはシングルスレッドのみで、Yappiはマルチスレッドですが、ハングアップの原因となります。私はcProfilerを各スレッドに追加し、それらの統計情報をまとめて、これらの時折の一時停止中にプロファイル統計だけを必要とするため、常にクリアするように調整する必要があります(通常実行中のノイズで応答が失われます)。試行できますが、問題があると思われます。他に何も現れなければそこに行くだろうと思う。 –

答えて

7
を使用して近どこ午前メモリの128ギガバイトを持っていると niceを削除しようとしています

OK。私は自分自身の質問に答えます。はい、これまでに3ヶ月以上かかるのです。

大規模な「システム」CPUスパイクや関連する一時停止の原因となるのは、PythonのGILスラッシングであるようです。ここにはgood explanation of where the thrashing comes fromがあります。このプレゼンテーションでも正しい方向に私を指摘しました。

Python 3.2 introduced a new GIL implementationこのスラッシングを避けるためです。結果は、(上記のプレゼンテーションから採取された)単純なねじ例を示すことができる:私のMacBook Proで

from threading import Thread 
import psutil 

def countdown(): 
    n = 100000000 
    while n > 0: 
     n -= 1 

t1 = Thread(target=countdown) 
t2 = Thread(target=countdown) 
t1.start(); t2.start() 
t1.join(); t2.join() 

print(psutil.Process().cpu_times())  

のPython 2.7.9で、これは「ユーザー」CPUと「システム」の13.2sの14.7sを使用しますCPU。

Python 3.4では15.0秒の「ユーザー」(わずかに多く)が使用されますが、「システム」はわずか0.2秒です。

GILはまだ存在しますが、コードがシングルスレッドの場合と同じ速度で実行されますが、カーネル( 'システム')のCPU時間として現れるPython 2のGILの競合をすべて回避します。この競合は、元の質問の問題を引き起こしていたと私は信じています。

更新

CPUの問題への追加の原因は、OpenCVの/ TBBであることが判明しました。このSO questionに完全に文書化されています。

関連する問題