ロックフリーのアルゴリズムを検証するにはどうすればよいですか?
-
20-09-2019 - |
質問
理論的には、ロックフリー アルゴリズムの検証をブルート フォースで実行することは少なくとも可能であるはずです (交差する関数呼び出しの組み合わせは非常に多くあります)。ロックフリー アルゴリズムが正しいことを実際に証明するために利用できるツールや正式な推論プロセスはありますか (理想的には、競合状態や ABA 問題もチェックできるはずです)。
注記:1つの点だけを証明する方法を知っている場合(例:ABA 問題から安全であることのみを証明してください)または私が言及していない問題については、とにかく解決策を投稿してください。最悪のシナリオでは、各方法を順番に実行して完全に検証できます。
解決
あなたは間違いなく SPINモデルチェッカを試してみてください。
あなたは内部的にスピンPromelaモデルと呼ばれる簡単なCのような言語でプログラムのようなモデルは、ステートマシンに変換書きます。モデルは、複数の並列プロセスを含めることができます。
あなたはをテストしたいのどのような条件のためにその後、何スピンは各プロセスからチェック指示
のののすべての可能なインタリーブである - レース条件の通常、不在、デッドロックからの解放など、これらのテストのほとんどは、簡単にassert()
文を使用して書き込むことができます。アサーションに違反する可能性の実行順序がある場合は、シーケンスは、そうでない場合は、あなたが「オールクリア」が与えられる、プリントアウトされます。
(まあ、実際には、それは、これを達成するために多くの愛好家と高速なアルゴリズムを使用していますが、それは効果である。デフォルトでは、すべての到達可能なプログラムの状態がチェックされます。)
これはの信じられないのプログラムであり、それは/ <2001 ACMシステムソフトウェア賞を受賞しましたA>(他の受賞者は、Unix、ポストスクリプトは、Apache、TeXに含まれます)。私は非常に迅速にそれを使用して開始し、数日中にPromelaモデルでのMPI関数MPI_Isend()
とMPI_Irecv()
のモデルを実装することができたました。スピンIの試験のためにPromelaモデルに横切って変換されたパラレルコードのセグメントにトリッキーの競合状態のカップルを発見した。
他のヒント
スピンは確かに優れたものと考え Relacyレース検出器 によるDmitriy V'jukov.この目的に構築された検証並行アルゴリズムを含む非ブロック(待-/ロックフリー)アルゴリズムでオープンソースの布ライセンスします。
Relacyを提供POSIXには、Windowsの同期プリミティブ(ミューテックス、条件変数に、セマフォ、CriticalSections win32イベント連動*など)ので、実際のC++実装を送り込むことができるRelacy検証実験を行いました。必要なの開発を別途モデルのアルゴリズムとPromelaもやらせていただきました。
Relacy contains C++0x std::atomic
(明示的なメモリの発注を勝ちです!) で利用できるプリプロセッサ #defines
ボRelacyの実施およびご自身のプラットフォームならではの原子の実施tbb::原子, ブ::原子, します。
ケジューリング制御:ランダム、コンテキスト行き、検索(全interleavings)をご利用頂けます。
以下に例を示しますRelacyます。いくつかの注意:
- の
$
はRelacyマクロの記録を実行す。 rl::var<T>
フラグが"正常"(非原子力変動要因も考慮に入れる必要があるとして証を行います。
コード:
#include <relacy/relacy_std.hpp>
// template parameter '2' is number of threads
struct race_test : rl::test_suite<race_test, 2>
{
std::atomic<int> a;
rl::var<int> x;
// executed in single thread before main thread function
void before()
{
a($) = 0;
x($) = 0;
}
// main thread function
void thread(unsigned thread_index)
{
if (0 == thread_index)
{
x($) = 1;
a($).store(1, rl::memory_order_relaxed);
}
else
{
if (1 == a($).load(rl::memory_order_relaxed))
x($) = 2;
}
}
// executed in single thread after main thread function
void after()
{
}
// executed in single thread after every 'visible' action in main threads
// disallowed to modify any state
void invariant()
{
}
};
int main()
{
rl::simulate<race_test>();
}
コンパイルと通常のコンパイラ(Relacyはヘッダのみ)を走らせると実行ファイル:
struct race_test DATA RACE iteration: 8 execution history: [0] 0: atomic store, value=0, (prev value=0), order=seq_cst, in race_test::before, test.cpp(14) [1] 0: store, value=0, in race_test::before, test.cpp(15) [2] 0: store, value=1, in race_test::thread, test.cpp(23) [3] 0: atomic store, value=1, (prev value=0), order=relaxed, in race_test::thread, test.cpp(24) [4] 1: atomic load, value=1, order=relaxed, in race_test::thread, test.cpp(28) [5] 1: store, value=0, in race_test::thread, test.cpp(29) [6] 1: data race detected, in race_test::thread, test.cpp(29) thread 0: [0] 0: atomic store, value=0, (prev value=0), order=seq_cst, in race_test::before, test.cpp(14) [1] 0: store, value=0, in race_test::before, test.cpp(15) [2] 0: store, value=1, in race_test::thread, test.cpp(23) [3] 0: atomic store, value=1, (prev value=0), order=relaxed, in race_test::thread, test.cpp(24) thread 1: [4] 1: atomic load, value=1, order=relaxed, in race_test::thread, test.cpp(28) [5] 1: store, value=0, in race_test::thread, test.cpp(29) [6] 1: data race detected, in race_test::thread, test.cpp(29)
最近のバージョンのRelacyをJavaメモリのCLIモデルがいなものでした。
データ競合検出は NP の難しい問題です [Netzer&Miller 1990]
Lockset と DJit+ というツールについて聞きました ( それを教える CDPコース内)。スライドを読んで、何を参照しているのかをグーグルで調べてみてください。いくつかの興味深い情報が含まれています。
私はあなたが使用しているもののプラットフォームや言語がわからない - しかし、.NETプラットフォーム上で<のhref = "http://channel9.msdn.com/shows/Going+Deepと呼ばれるマイクロソフトリサーチプロジェクトがあります/ CHESS-自動-同時実行・テスト・ツール/」のrel = "nofollowをnoreferrer">私たちは、マルチスレッドのコンポーネントをやってのそれらを助けることで、非常に有望探しているチェスに - ロックフリーを含む
。私は、それを膨大な量を使用していませんでした心ます。
これは、明示的に実際に野生にあなたのバグを強制的にタイトな可能な方法でスレッドをインターリーブすることによって(粗製の説明)動作します。また、一般的な間違いや悪いパターンを見つけるためのコード分析 - 。コード解析に類似の
過去には、私はまた、問題のコードの特別なバージョンを構築した余分な状態追跡情報を追加(の#ifブロックなどを介して)。私は、ユニットテストの中に浸すことができますカウント、バージョンなど。
それに伴う問題は、それはあなたのコードを書くために多くの時間がかかり、あなたが常に存在すでにのコードの基本的な構造を変更することなく、原料のこの種を追加することはできませんということです。
あなたは本当にロックフリーのコードを(徹底的小さなインスタンスをテストするために反対に)検証したい場合は、VCCを使用することができます( http://vcc.codeplex.com の)、いくつかの興味深いロックフリーアルゴリズム(ハザードポインタを使用して例えばロックフリーリストやサイズ変更可能なハッシュテーブル、楽観的なマルチバージョントランザクションを検証するために使用されている同時Cコードのための演繹的検証処理、MMU仮想化、様々な同期プリミティブ、等)。これは、モジュール式の検証を行い、そして(約20KLOCまで)工業用コードの自明でないチャンクを確認するために使用されています。
ただし、VCCが検証ではなく、バグの狩猟のツールであること。あなたはそれが検証するために得るためにあなたのコードにかなりの注釈を行う必要がありますし、学習曲線は、ビット急なことができます。 (ほとんどのツールがそうであるように)、それは、順次一貫性を前提としていることにも注意します。
ところで、ピアレビューは、同時アルゴリズム(あるいはシーケンシャル1)を検証するための良い方法ではありません。重要な雑誌に同時アルゴリズムを公開有名な人々の長い歴史が唯一のバグが年後に発見したために、あります。