8

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

プログラムは正常に動作しているように見えます (毎回同じ結果が得られますが、同期が使用されていない場合はそうではありません) が、インテル® Parallel Inspectorは値 += 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

3 に答える 3

4

Parallel Inspector のデータ競合に関するドキュメントでは、クリティカル セクションまたはミューテックスを使用して Windows での競合を修正することを提案しています。Parallel Inspector が、あなたが考案した可能性のある他のロック メカニズムを認識する方法を知っていることを示唆するものは何もありません。

新しいロック メカニズムを分析するためのツールは、コード内の可能なすべてのパスを調べる静的ツールである傾向があり、Parallel Inspector のドキュメントでは、コードを 1 回実行することを暗示しています。

新しいロック メカニズムを試してみたい場合、学術文献で使用されている最も一般的なツールはSpin モデル チェッカーです。状態空間を縮小する可能性のあるESPもありますが、それが並行問題に適用されているかどうかはわかりません。Intel Parallel Inspector は、これらのツールほど複雑ではないように見えますが、ヒューリスティックを使用して一般的に発生する問題をチェックするように設計されています。

于 2009-09-24T10:58:00.503 に答える
2

私と同様の状況にある他の貧しい人々のために:インテルは、まさにこの種のことを行うための一連のインクルードとライブラリを提供しています。Inspector のインストール ディレクトリ (インストール ディレクトリに \include、\lib32、および \lib64 が表示されます) で、これらの資料を確認します。それらの使用方法に関するドキュメント (2018 年 6 月現在、Intel はリンクの一貫性を維持することについて何も気にしません):

https://software.intel.com/en-us/inspector-user-guide-windows-apis-for-custom-synchronization

3 つの機能があります。

void __itt_sync_acquired(void *addr)
void __itt_sync_releasing(void *addr)
void __itt_sync_destroy(void *addr)
于 2011-04-03T23:32:41.657 に答える
1

次のように実装する必要があると確信しています。

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

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

   void Unlock() { InterlockedExchange(&lockValue, 0); }
};
于 2009-09-24T10:22:54.723 に答える