4

計算クラスター全体で実行される C アプリケーションを作成しています (condor を使用)。問題のあるコードを明らかにするために多くの方法を試しましたが、役に立ちませんでした。

手がかり:

  • 15 台のマシンで 2 日間コードを実行すると、平均して 2 つまたは 3 つのセグメンテーション違反 (シグナル 11) が発生します。
  • コードをローカルで実行すると、segfault が発生しません。自宅のマシンで 3 週間近く実行しました。

試み:

  • ローカルで valGrind のコードを 4 日間実行しましたが、メモリ エラーは発生しませんでした。
  • プログラムの状態の一部を出力できるように、独自のシグナル ハンドラーを定義して segfault シグナルをキャプチャしました。
  • これで、segfault が発生したときに、バックトレースを使用して現在のスタックを出力できます。
  • 変数値を出力できます。
  • 現在の行番号に設定される変数を作成しました。
  • また、問題が解決すればセグメンテーション違反が見つかることを期待して、コードのチャンクをコメントアウトしようとしました。

悲しいことに、出力される行番号はかなりランダムです。スタックトレースで何ができるか完全にはわかりません。セグメンテーション違反が発生した関数のアドレスのみを記録すると仮定して正しいですか?

疑惑:

  • コンドルがマシン間でジョブを移動するために使用するチェック ポインティング システムは、メモリの破損に対してより敏感であると思われます。これがローカルで見られない理由です。
  • そのインデックスがバグによって破損しており、これらのインデックスがセグメンテーション違反を引き起こしていること。これは、セグメンテーション違反がかなりランダムな行番号で発生しているという事実を説明します。

アップデート

これをさらに調査すると、次のリンクが見つかりました。

更新 2

Greg は、condor のログを見て、「コンドルがチェックポイントから実行可能ファイルを再起動したときにセグメンテーション違反を関連付ける」ことを提案しました。ログを見ると、segfaults はすべて再起動直後に発生します。すべての障害は、ジョブがあるタイプのマシンから別のタイプのマシンに切り替わったときに発生するようです。

更新 3

コンドル送信ファイルの「requiremets」フィールドを問題に設定することで、ホスト間の違いによって引き起こされていたセグメンテーション違反は完全になくなりました。

個々のマシンを設定できます:

requirements = machine == "hostname1" || machine == "hostname2"

またはマシンのクラス全体:

requirements = classOfMachinesName

要件の例はこちら

4

5 に答える 5

2

可能であれば、デバッグでコンパイルし、gdb で実行してください。または、コア ダンプを取得し、それをデバッガーにロードします。

mpich にはデバッガーが組み込まれていますが、市販の並列デバッガーを購入することもできます。

次に、コードをステップ実行して、デバッガーで何が起こっているかを確認できます

http://nmi.cs.wisc.edu/node/1610

http://nmi.cs.wisc.edu/node/1611

于 2010-09-10T01:54:57.947 に答える
2

セグメンテーション違反が発生したときにコア ダンプを作成できますか? 次に、このダンプをデバッグして、クラッシュしたときのコードの状態を把握することができます。

フォルトの原因となった命令を調べます。それは有効な命令でしたか、それともデータを実行しようとしていますか? 有効な場合、どのメモリにアクセスしようとしていますか? このポインターはどこから来たのですか。障害の場所を絞り込む必要があります (スタックの破損、ヒープの破損、初期化されていないポインター、無効なメモリへのアクセス)。破損している場合は、破損した領域に明らかなデータ (シンボルへのポインター、構造内の何かのように見えるデータなど) があるかどうかを確認します。メモリ アロケータには、破損をデバッグする機能が組み込まれている場合があります ( MALLOC_CHECK_Linux またはMallocGuardEdgesMac OS の場合を参照)。これらの一般的なケースは、free() されたメモリを使用しているため、malloc() / free() のペアをログに記録すると役立つ場合があります。

于 2010-09-10T01:56:49.400 に答える
1

コンドル_コンパイル ツールを使用してコードをコンドル チェックポイント コードに再リンクした場合、通常のリンクとはいくつかの点が異なります。最も重要なことは、コードを静的にリンクし、独自の malloc を使用することです。もう 1 つの大きな違いは、condor がそれを外部のマシンで実行することです。その環境では、問題が発生すると予想される環境とは十分に異なる可能性があります。

consdor_compile によって生成された実行可能ファイルは、condor システムの外部でスタンドアロン バイナリとして実行可能です。コンドルの外で、condor_compile から生成されたバイナリをローカルで実行すると、セグメンテーション違反が表示されますか?

そうでない場合、セグメンテーション違反を、コンドルがチェックポイントから実行可能ファイルを再起動したときに関連付けることができます (これがいつ発生したかは、ユーザー ログでわかります)。

于 2010-09-15T00:58:14.060 に答える
0

あなたは私が考えていることのほとんどを試しました。私が提案する他の唯一のことは、多くのログ コードの追加を開始し、エラーが発生している場所を絞り込めることを願っています。

于 2010-09-10T01:39:38.107 に答える
0

あなたが言わないことの1つは、問題を解決するためにどれだけの柔軟性が必要かということです. たとえば、システムを停止させてアプリケーションを実行することはできますか? また、これらのクラッシュを解決することはどれほど重要ですか?

ほとんどの場合、あなたがそうしていると思います。これには多くのリソースが必要になる場合があります。

短期的なステップは、各変数の大量の「アサート」(半手書き)を配置して、変更したくないときに変更されていないことを確認することです。これは、長期的なプロセスを経るにつれて機能し続ける可能性があります。

長期的には、2 つのクラスター (自宅のコンピューターと VM など) で実行してみてください。まだセグメンテーション違反が表示されますか。そうでない場合は、セグメンテーション違反が発生するまでクラスター サイズを増やしてください。

( segfaults を取得するため)最小構成で実行し、クラッシュするまですべての入力を記録します。記録した入力を使用してシステムの実行を自動化し、最小限の入力で一貫してクラッシュできるようになるまで微調整します。

そんな時は周りを見渡してください。それでもバグが見つからない場合は、それらの実行で収集した追加データを使用して再度質問する必要があります。

于 2010-09-10T03:07:59.047 に答える