1

Cプログラムで長時間実行されているwhileループでソフトロックアップ/無応答を防ぐ正しい方法はどのようになりますか?

(dmesg はソフトロックアップを報告しています)

擬似コードは次のようになります。

while( worktodo ) {
  worktodo = doWork();
}

私のコードはもちろんもっと複雑で、進行状況を報告するために 1 秒に 1 回実行される printf ステートメントも含まれていますが、問題は、この時点でプログラムが ctrl+c に応答しなくなることです。

私が試したものは機能します(ただし、代替手段が必要です):

  • ループの反復ごとに printf を実行します (理由はわかりませんが、プログラムはそのように再び応答します (???)) - 不要な printf 呼び出しのために多くのパフォーマンスが浪費されます (各 doWork() 呼び出しはそれほど長くかかりません)
  • sleep/usleep/... を使用する - プログラム全体がすでにフルスピードで数時間実行されているため、(処理) 時間の無駄のようにも思えます

私が考えているのは、ある種の process_waiting_events() 関数などであり、別のシェルで kill を使用してプログラムを停止できるため、通常のシグナルは正常に機能しているようです。

追加の背景情報: 私はGWANを使用しており、私のコードは main.c の「メンテナンス スクリプト」内で実行されています。これは、私が知る限り、メイン スレッドで実行されているようです。

どうもありがとうございました。

PS: はい、ソフト ロックアップに関して見つけた他のすべてのスレッドを確認しましたが、それらはすべて、ソフト ロックアップが発生する理由を尋ねているようですが、理由はわかっており、それらを防止する方法が必要です。

PPS: プログラムを最適化する (実行時間を短縮する) ことは、実際には解決策ではありません。29GB の bz2 ファイルを処理して、約 400GB の xml に抽出し、シングル スレッドで毎秒約 10-40MB の速度で処理しているため、最大速度では、I/O に拘束され、それでも数時間実行されます。

4

3 に答える 3

1

スレッドを使用して提示された答えはおそらくオプションかもしれませんが、実際には問題を別のスレッドに移すだけです。結局私の解決策は使用していた

sleep(0)

sched_yield / pthread_yield もテストしましたが、どちらも実際には役に立ちませんでした。残念ながら、Linux で sleep(0) を文書化する適切なリソースを見つけることができませんでしたが、Windows の場合、文書には、値 0 を使用すると、スレッドが現在の cpu スライスの残りの部分を生成できると記載されています。

sleep(0) は、おそらくLinux でタイマー スラックと呼ばれるものに依存していることが判明しました。これに関する記事は、http: //lwn.net/Articles/463357/にあります。

もう1つの可能性は、nanosleep(&(struct timespec){0}, NULL)必ずしもタイマースラックに依存していないように見える使用です-ナノスリープ状態のLinuxマニュアルページでは、要求された間隔がクロック粒度を下回っている場合、クロック粒度に切り上げられます。Linuxでは、マニュアルページによるとCLOCK_MONOTONICに依存します. したがって、0 ナノ秒の値は完全に有効であり、クロックの粒度が 0 になることはあり得ないため、常に機能するはずです。

これが他の誰かにも役立つことを願っています;)

于 2013-09-11T11:00:45.103 に答える