2009-09-24 28 views
9

我在Windows中使用Interlocked函數做了一個非常簡單的自旋鎖,並在雙核CPU上進行了測試(兩個線程遞增了一個變量)。英特爾Inspector報告我的自旋鎖實現中的數據競爭

程序似乎工作正常(它提供了相同的結果每一次,這是不是在沒有使用同步的情況下),但英特爾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

Parallel Inspector中對data race文檔建議使用臨界區或互斥修復Windows上的比賽。沒有任何內容表明Parallel Inspector知道如何識別您可能發明的任何其他鎖定機制。

工具的新的鎖定機制的分析往往是該看看通過代碼每一個可能的路徑靜電工具,Parallel Inspector中的文檔意味着它一旦執行代碼。

如果你想用新的鎖定機制來實驗中,最常用的工具,我已經看到了學術文獻採用的是Spin model checker。也有ESP,這可能會減少狀態空間,但我不知道它是否已應用於併發問題,還有mobility workbench如果您可以在pi演算中解決您的問題,可以給出分析。英特爾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不能再被使用(該類還有一個可以自動釋放鎖的析構函數)。我想,我嘗試了你所說的,並且它是一樣的:程序正常工作,但英特爾Parallel Inspector表示存在競爭狀況。也許檢查員有一個錯誤?但可能不會:( – 2009-09-24 10:38:40

+0

你也應該用長開始,而不是做明確的轉換,並在構造函數不帶參數,只是啓動它解鎖。如果創建它所需要的東西有它鎖定,首先,他們可以只創建後但在共享之前鎖定@Igratian - 你不需要RAII在這種情況下,由於析構函數無關清理(它只是一個長) – 2009-09-24 13:31:52

+0

編輯。不會麻煩添加解構器......因爲這個問題不能完全糾正他的代碼。我只是想解決他的問題。 – Goz 2009-09-24 13:56:48

2

對於類似的情況給我其他貧困鄉親:英特爾確實提供了一套包括和準確地做這樣的事情庫。檢查Inspector安裝目錄(您將在安裝目錄中看到\ include,\ lib32和\ lib64)。關於如何使用它們(作爲十二月2014年)文檔:

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 2012-06-25 12:44:04

+0

不客氣。 – johnwbyrd 2012-08-18 16:16:23