2009-06-23 40 views
20

Interlocked.Increment(ref x)快或慢x++不同的平臺上整型和長?性能Interlocked.Increment

+0

正如其他人指出,這是不一樣的東西。這就是說,根據http://msdn.microsoft.com/en-us/magazine/cc163726.aspx一個Interlocked.Increment需要一些14nS(或約71'000'000每秒),所以我不會太擔心關於性能 – smirkingman 2012-09-27 20:03:22

+0

Interlocked.Increment旨在用於線程環境 – EProgrammerNotFound 2013-08-08 15:29:53

回答

37

它是慢,因爲它迫使行動發生原子和它作爲一個內存屏障,消除處理器的重新排序記憶能力訪問指令周圍。它不打算爲x的完全替代++ -

當你想要的動作來,可以在線程之間共享狀態原子您應該使用Interlocked.Increment。

3

它會一直比較慢,因爲它必須執行CPU總線鎖定而不是更新寄存器。然而現代CPU實現了接近寄存器的性能,因此即使在實時處理中它也可以忽略不計。

+3

雖然X86 CPU在互鎖操作期間執行一個總線鎖定,但所有提供互鎖操作的CPU都不需要一個總線鎖定。某些CPU能夠明顯地表示它們已經預留了單個高速緩存行,並且可以在沒有總線鎖的情況下在該高速緩存行上執行互鎖操作。 – Adisak 2009-10-30 16:33:38

4

速度較慢。但是,這是我知道的在標量變量上實現線程安全性的最高性能的通用方法。

+1

`volatile'在標量上表現更好,但是它的缺點是需要使用好的編碼實踐。 – Abel 2009-11-12 12:02:40

+2

小心易波;某些處理器體系結構(x86/x64)能夠重新排序對內存的訪問,而不管該內存是否被編譯器標記爲易失性內存。 – 2009-11-26 17:49:46

6

想想看一會兒,你會發現一個Increment呼叫不能有任何快於增量運算符的簡單應用。如果是,那麼編譯器的增量操作符的實現將在內部調用Increment,並且它們會執行相同的操作。

但是,正如您通過自己測試所看到的那樣,它們不會執行相同的操作。

這兩個選項有不同的目的。一般使用增量運算符。當你需要操作是原子操作時,使用Increment,並確保該變量的所有其他用戶也正在使用互鎖操作。 (如果他們不是所有的合作,那麼它並沒有真正的幫助。)

+0

不,它不會 - Interlocked.Increment無法在屬性上調用,而++運算符可以。因此,++將無法調用它。 – SLaks 2009-06-23 17:55:21

12

在我們的經驗InterlockedIncrement()等人在Windows上是相當顯著的影響。在一個示例中,我們能夠消除互鎖並使用++/- 來代替。僅此一項將運行時間從140秒縮短到110秒。我的分析是,互鎖迫使記憶往返(否則其他核心會怎麼看?)。 L1高速緩存的讀/寫是在10個時鐘週期,但讀/存儲器寫更像100

在此示例的情況下,我估計遞增/遞減操作的數量在約1十億。所以在2Ghz的CPU上,這個大概是++/- 5秒,而互鎖是50秒。將差異傳播給幾個線程,接近30秒。

4

我的性能比較試驗:

揮發性:65174400

鎖:62428600

互鎖:113248900

TimeSpan span = TimeSpan.FromSeconds(5); 

object syncRoot = new object(); 
long test = long.MinValue; 

Do(span, "volatile",() => { 

    long r = Thread.VolatileRead(ref test); 

    r++; 

    Thread.VolatileWrite(ref test, r); 
}); 

Do(span, "lock",() => 
{ 
    lock (syncRoot) 
    { 
     test++; 
    } 
}); 

Do(span, "interlocked",() => 
{ 
    Interlocked.Increment(ref test); 
});