2011-12-16 101 views
5

這兩個有什麼區別?差異linq和plinq

什麼是比較的最佳方式?

它總是更好的plinq?

當我們使用plinq?

+0

這裏有一些很好的信息http://www.scip.be/index.php ?Page = ArticlesNET08&Lang = EN – user1231231412 2011-12-16 21:59:16

+0

我認爲假設使用PLINQ總是比較好,LINQ將不存在。結果:使用PLINQ並不總是更好。 – jason 2011-12-16 22:03:09

回答

2

PLinq是Linq的並行版本。有些查詢可以在多個線程上執行,然後PLinq會提高性能。

但是,其他查詢不能並行執行,否則會給出錯誤結果。所以何時使用PLinq是你應該爲每個查詢決定的事情,並確保性能實際上增加。

MSDN有很多關於它的文檔。

8

Linq是一個技術集合,它們一起工作來解決類似的問題 - 在所有這些技術中你都有一個數據源(xml文件或文件,數據庫內容,內存中對象的集合),並且你想要檢索部分或全部數據並以某種方式對其執行操作。 LINQ的工作是在這個系列問題的共性使得:

var brithdays = from user in users where 
    user.dob.Date == DateTime.Today && user.ReceiveMails 
    select new{user.Firstname, user.Lastname, user.Email}; 
foreach(bdUser in birthdays) 
    SendBirthdayMail(bdUser.Firstname, bdUser.Lastname, bdUser.Email); 

以及等效(明確使用LINQ相關的類和方法與傳統的C#語法):

var birthdays = users 
    .Where(user => user.dob.Date == DateTime.Today) 
    .Select(user => new{user.Firstname, user.Lastname, user.Email}); 
foreach(bdUser in birthdays) 
    SendBirthdayMail(bdUser.Firstname, bdUser.Lastname, bdUser.Email); 

都是例子的代碼可以工作,無論它是否會轉化爲數據庫調用,解析xml文檔,還是通過對象數組進行搜索。

唯一的區別是什麼樣的對象users是。如果它是一個列表,數組或其他可枚舉集合,它將是linq-to-objects,如果它是一個System.Data.Linq.Table它將是sql的linq。前者會導致內存中操作,後者會導致SQL查詢,然後儘可能晚地對內存中的對象進行反序列化。

如果這是一個ParallelQuery - 通過在內存中的枚舉集合調用.AsParallel產生 - 那麼該查詢將在-memroy執行,並行化(大部分時間),以便由多個線程執行的 - 理想地保持每個核心忙於推進工作。

顯然這裏的想法是更快。當它運作良好時,它確實如此。

雖然有一些缺點。

首先,總會有一些開銷讓並行化進行,即使在最終不能並行化的情況下也是如此。如果沒有足夠的數據完成工作,這種開銷將超出任何潛在收益。

其次,並行處理的好處取決於可用的內核。如果查詢不會阻塞4核機器上的資源,理論上會獲得4倍的加速(4個超線程可能會給您帶來更多甚至更少,但可能不會超過8倍,線程的CPU的某些部分翻倍並不會明顯增加兩倍)。對單核或者處理器親和性的相同查詢意味着只有一個核心可用(例如,在「web-garden」模式下的web服務器),那麼沒有加速。如果資源受到阻礙,仍然可以獲得收益,但收益取決於機器。

第三,如果有任何共享資源(可能是一個收集結果輸出到)在非線程安全的方式使用,它可以走得相當嚴重錯誤與不正確的結果,死機等

四,如果以線程安全的方式使用共享資源,並且線程安全來自鎖定,則可能存在足夠的爭用成爲解除並行化的所有好處的瓶頸。第五,如果你有一個四核機器在四個不同的線程上或多或少地使用相同的算法(可能在客戶端 - 服務器情況下由於四個客戶端,或者來自一組類似的桌面情況在這個過程中任務更高),那麼他們就會盡可能地利用這些核心。將算法中的工作分開以便在所有四個內核中進行處理意味着您已經從四個線程移動到每個內核,16個線程與四個內核交戰。充其量也是一樣的,可能的開銷會讓它稍微惡化。

可以仍然是很多情況下的主要勝利,但上面應該說明它並不總是。

0

考慮避免anonymous typesPLINQ工作時,因爲根據Threading in C#, by Joe Albahari

匿名類型(即類和因此引用類型)招致基於堆的分配和隨後的垃圾收集的成本。

(...)

基於堆棧的分配是高度並行(因爲每個線程都有自己的堆棧),而所有線程都必須爲同一個堆競爭 - 由單一的內存管理和垃圾收集管理。

2

由於進行AsParallel透明並行化LINQ查詢,出現這樣的問題,「你爲什麼不只是微軟並行標準查詢操作符,使PLINQ默認?」

有許多的原因選擇在進近中。首先,爲了使PLINQ有用,必須進行合理數量的計算密集型工作,以便將其用於工作線程。大多數LINQ to Objects查詢的執行速度非常快,不僅平行化不必要,而且分區,整理和協調額外線程的開銷實際上可能會減慢速度。

此外:

一個PLINQ查詢(默認情況下)的輸出可以從LINQ查詢不同相對於元件排序。

下面的查詢操作阻止並行查詢,除非源元素是在原來的標定位置:

走,TakeWhile,跳過和SkipWhile選擇,的SelectMany的索引的版本,並ElementAt的大多數查詢運算符更改元素的索引位置(包括刪除元素的位置,如Where)。這意味着如果你想使用前面的操作符,他們通常需要在查詢的開始。

下面的查詢操作是並行的,但使用昂貴的分區策略,有時可以比順序處理慢:

加入,的GroupBy,羣組加入,層次分明,聯盟,交叉,除了在總量上運營商的種子重載他們的標準化身不是可並行化的 - PLINQ提供特殊的重載來處理這個問題。

何時使用PLINQ 很容易在現有的應用程序中搜索LINQ查詢並試驗並行化。這通常是徒勞的,因爲LINQ顯然是最好的解決方案的大多數問題傾向於執行得非常快,所以不會從並行化中受益。一個更好的方法是找到一個CPU密集型瓶頸,然後考慮「這可以表示爲LINQ查詢嗎?」(這種重組的一個受歡迎的副作用是LINQ通常會使代碼更小且更具可讀性。)

PLINQ非常適合於令人尷尬的並行問題。它也適用於結構化阻塞任務,例如一次調用多個Web服務(請參閱調用阻塞或I/O密集函數)。

PLINQ對於成像來說可能是一個糟糕的選擇,因爲將數百萬像素整理成輸出序列會造成瓶頸。相反,最好將像素直接寫入數組或非託管內存塊,並使用並行類或任務並行性來管理多線程。 (但是,如果圖像處理算法自然適用於LINQ,則可能會失敗使用ForAll的結果整理。)