2009-09-24 13 views
9

Windowsのインターロック機能を使用して非常に簡単なスピンロックを作成し、デュアルコアCPU(変数をインクリメントする2つのスレッド)でテストしました。Intel Inspectorはスピンロック実装のデータ競合を報告します

プログラムがOKを動作するようです(それは同じ結果に何の同期が使用されていない場合ではありませんたびに、与え)、しかしIntelはインスペクタ値+ = jでの競合状態があることを述べているパラレル(下記のコードを参照してください)。 SpinLockではなくクリティカルセクションを使用すると警告が消えます。

私のSpinLockの実装は正しいですか?使用されているすべての操作がアトミックで、適切なメモリ障壁があり、競合状態に陥らないため、実際には奇妙です。

class SpinLock 
{ 
    int *lockValue; 
    SpinLock(int *value) : lockValue(value) { } 

    void Lock() { 
     while(InterlockedCompareExchange((volatile LONG*)lockValue, 1, 0) != 0) { 
      WaitABit(); 
     } 
    } 

    void Unlock() { InterlockedExchange((volatile LONG*)lockValue, 0); } 
}; 

テストプログラム:

static const int THREADS = 2; 
HANDLE completedEvents[THREADS]; 
int value = 0; 
int lock = 0; // Global. 

DWORD WINAPI TestThread(void *param) { 
    HANDLE completed = (HANDLE)param; 
    SpinLock testLock(&lock); 

    for(int i = 0;i < 1000*20; i++) { 
     for(int j = 0;j < 10*10; j++) { 
      // Add something to the variable. 
      testLock.Lock(); 
      value += j; 
      testLock.Unlock(); 
     } 
    } 
    SetEvent(completed); 
} 

int main() { 
    for(int i = 0; i < THREADS; i++) { 
     completedEvents[i] = CreateEvent(NULL, true, false, NULL); 
    } 
    for(int i = 0; i < THREADS; i++) { 
     DWORD id; 
     CreateThread(NULL, 0, TestThread, completedEvents[i], 0, &id); 
    } 

    WaitForMultipleObjects(THREADS, completedEvents, true, INFINITE); 
    cout<<value; 
} 

答えて

4
data raceため

パラレルインスペクタのマニュアルは、クリティカルセクションやミューテックスを使用することを提案していますWindowsでレースを修正するParallel Inspectorには、あなたが考案した他のロック機構をどのように認識するかが分かっていることは示唆されていません。

新規ロック機構の解析ツールは、コード内のすべての可能なパスを見る静的ツールである傾向がありますが、Parallel Inspectorのドキュメンテーションはコードを一度実行することを意味します。

新しいロック機構を試したいのであれば、私が学術文献で使用している最も一般的なツールはSpin model checkerです。状態空間を縮小する可能性のあるESPもありますが、それが同時問題に適用されているかどうかわかりません。また、pi-calculusで問題を解決できるかどうかを分析するmobility workbenchもあります。インテル®Parallel Inspectorは、これらのツールほど複雑ではありませんが、ヒューリスティックを使用して一般的に発生する問題をチェックするように設計されています。

1

私は次のように実施されるべきであるかなり確信している:

class SpinLock 
{ 
    long lockValue; 
    SpinLock(long value) : lockValue(value) { } 

    void Lock() { 
     while(InterlockedCompareExchange(&lockValue, 1, 0) != 0) { 
      WaitABit(); 
     } 
    } 

    void Unlock() { InterlockedExchange(&lockValue, 0); } 
}; 
+0

は、あなただけの周りのint型という、私は何をすべきかとほぼ同じである提案は何ロックスピンはクラスに含まれています...これは、RAIIはもはや使用できないので(クラスには自動的にロックを解除するデストラクタもあります)、不利になります。あなたが言ったことを試してみました。それは同じです。プログラムは正しく動作しますが、Intel Parallel Inspectorは競合状態があると言います。インスペクタにバグがありますか?しかし、おそらくそうではありません:( –

+0

あなたはまた、明示的なキャストを行うのではなく、最初から始めるべきであり、コンストラクタでパラメータを取らず、ロックを解除して起動する必要があります。 @Igratian - この場合、デストラクタはクリーンアップするものがないので(ちょっと長い)、RAIIは必要ありません。 –

+0

編集されました。デストラクタの追加を気にするつもりはありません。なぜなら、質問はコードを完全に修正することを保証するものではないからです。私はちょうど彼の問題を解決しようとしていた。 – Goz

2

私と同じような状況にある他の貧しい人々のために:インテルは、まさにこの種のことを行うためのインクルードとライブラリのセットを提供しています。 Inspectorのインストールディレクトリ(インストールディレクトリに\ include、\ lib32、\ lib64が表示されます)をチェックしてください。 (2014年12月の時点で)それらを使用する方法についてのドキュメント:

https://software.intel.com/sites/products/documentation/doclib/iss/2013/inspector/lin/ug_docs/index.htm#GUID-E8B4A8F7-45C3-489C-A5E3-1C9CC525BA9C.htm

3つの機能があります。

void __itt_sync_acquired(void *addr) 
void __itt_sync_releasing(void *addr) 
void __itt_sync_destroy(void *addr) 
+0

私は自分自身のスピンロックミューテックスでこれをテストし、期待どおりに動作します(データレースはParallel Inspectorレポートから消えます) – Julio

+0

ようこそ。 – johnwbyrd

関連する問題