2012-11-19 62 views
3

假設我有一些Particle S IN X,Y空間,我想他們正常化一切,使得平均X和Y是0PLINQ進行AsParallel()的ForAll()訪問資源

串行執行:

public void Normalise() 
{ 
    double avgX = 0.0; 
    double avgY = 0.0; 

    foreach (Particle p in Particles) 
    { 
    avgX += p.X; 
    avgY += p.Y; 
    } 

    avgX /= (double)Particles.Count; 
    avgY /= (double)Particles.Count; 

    foreach (Particle p in Particles) 
    { 
    p.X -= avgX; 
    p.Y -= avgY; 
    } 
} 

這個工作,而且性能也不錯,因爲它是爲O(n),但它的「易並行」。看看我的PLINQ實現:

public void PNormalise() 
{ 
    double avgX = 0.0; 
    double avgY = 0.0; 

    Particles.AsParallel().ForAll(p => 
    { 
    avgX += p.X; 
    avgY += p.Y; 
    }); 

    avgX /= (double)Particles.Count; 
    avgY /= (double)Particles.Count; 

    Particles.AsParallel().ForAll(p => 
    { 
    p.X -= avgX; 
    p.Y -= avgY; 
    }); 
} 

我不確定這裏的性能,但我會想象它會更好。問題是,粒子都是隨機跳躍的。我只能假設avgXavgY上的+=操作正在相互競爭,儘管它們已經相當原子了。

有什麼我可以做的,以解決它?我不能lock他們,因爲他們不是對象,但我不確定我想要反正因爲不鎖定相當昂貴?

+0

沒有「相當原子」這樣的東西,一個操作或者是原子的,或者不是。 – svick

回答

5

可以繞過經由並行LINQ的正常機械鎖的需要(或原子操作):

var avgX = Particles.AsParallel().Average(p => p.X); 
var avgY = Particles.AsParallel().Average(p => p.Y); 

Particles.AsParallel().ForAll(p => { p.X -= avgX; p.Y -= avgY }); 

由於求和的數目爲O(N)的操作,我將是如果極爲驚訝這部分時間佔用了很多時間。

+0

我每天都越來越熱愛LINQ ...... – Ozzah

1

使用

Particles.AsParallel().ForAll(p => 
{ 
    Interlocked.Add(avgX, p.X); 
    Interlocked.Add(avgY, p.Y); 
} 

做一個線程安全的原子加法。欲瞭解更多信息,請參閱Interlocked Class的文檔。

+0

更好的解決方案可能是做一個並行總和,它會自動爲你處理。 –

+1

'Interlocked.Add'只能重載'(ref int,int)'和'(ref long,long)',但我使用'double' – Ozzah

0

實際上,並行化這個O(n) - 算法不會帶來更好的性能,因爲您的內存訪問量與計算指令大致相同。

+0

I不知道JIT編譯器是否執行它,但它很可能會通過[SSE處理器擴展](http)將指令更改爲[SIMD指令](http://en.wikipedia.org/wiki/SIMD) ://en.wikipedia.org/wiki/Streaming_SIMD_Extensions)。 [這是一個博客](http://blogs.msdn.com/b/davidnotario/archive/2005/08/15/451845.aspx)以及一些關於CLR和擴展的更多信息,如SSE –

+0

是的,但是算法仍然是內存綁定的,所以CPU仍然大部分是空閒的,但是現在它所做的少數工作現在均勻地分佈在其內核中。 –

+0

@MathiasBecher:這樣的O(N)問題實際上對並行性非常好。如果問題規模變得更大,那麼大多數情況下,您可以投入更多硬件來執行與之前類似的操作。我同意,雖然它可能有點微不足道,除非你有類似N = 10^7的東西。 –