C# 並行編程 之 PLINQ 基本使用

來源:互聯網
上載者:User

標籤:plinq   並行計算   

PLINQ Summary

LINQ (LINQ) Language Integrated Query 可以方便的查詢並處理不同資料來源的資料。PLINQ Parallel LINQ不光擁有LINQ的功能,還添加了並行操作的介面,以方便使用並提高效率。

更詳細的資訊: https://msdn.microsoft.com/zh-cn/library/dd460688(v=vs.110).aspx

一個簡單的例子

用一個簡單的例子足以說明PLINQ的使用。
簡單的說明:
第一部分:先在一個文檔中查詢包含字母 “a”的單詞首先使用 LINQ進行查詢10000次,然後使用PLINQ進行同樣的測試,看看效率有多少提高。 AsParallel() 是主要用到的介面。

第二部分:計算Short類型所有數位和,同樣測試兩次使用LINQ和PLINQ。

第三部分:測試PLINQ的尋找排序功能。使用的介面分別為AsOrdered()和orderby
AsOrdered:保持資料在資料來源中的順序不變。
orderby:按使用者指定的順序進行排序,升序/降序

樣本程式:

using System;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Diagnostics;using System.Linq;using System.IO;namespace Sample6_1_plink_basic{    class Program    {        static int SumDefault(int[] array)        {            return array.Sum();        }        static int SumAsParallel(int[] array)        {            return array.AsParallel().Sum();        }        static string[] words = { "Day", "Car", "Land", "Road", "Sea", "Mountain", "River"};        static void Main(string[] args)        {            var customers = System.IO.File.ReadAllLines(@"D:\testdir\CSParallel_Program\Sample6-1 plink basic\target.txt");            int nCounter = 0;            Console.WriteLine("============================================================");            Console.WriteLine("TEST NORMAL LINQ");            Console.WriteLine("============================================================");            var swatchpn = Stopwatch.StartNew();            for (int i = 0; i < 10000; i++)            {                var normalkeyLetters = from line in customers                                       let keys = line.Split(‘ ‘)                                       from key in keys                                       where (key.Contains(‘a‘))                                       select key;                var normalkeyList = normalkeyLetters.ToList();                nCounter = normalkeyList.Count();            }            swatchpn.Stop();            Console.WriteLine("Word with letter a = {0}", nCounter);            Console.WriteLine("LINQ Use Time: {0}", swatchpn.Elapsed);            Console.WriteLine("\n\n");            Console.WriteLine("============================================================");            Console.WriteLine("TEST PARALLEL LINQ");            Console.WriteLine("============================================================");            nCounter = 0;            var swatchp = Stopwatch.StartNew();            for (int i = 0; i < 10000; i++)            {                var keyLetters = from line in customers.AsParallel()                                 let keys = line.Split(‘ ‘)                                 from key in keys.AsParallel()                                 where (key.Contains(‘a‘))                                 select key;                var keyList = keyLetters.ToList();                nCounter = keyList.Count();            }            swatchp.Stop();            Console.WriteLine("Word with letter a = {0}", nCounter);            Console.WriteLine("PLINQ Use Time: {0}", swatchp.Elapsed);            // Generate array.            int[] array = Enumerable.Range(0, short.MaxValue).ToArray();            const int m = 10000;            var s1 = Stopwatch.StartNew();            for (int i = 0; i < m; i++)            {                SumDefault(array);            }            s1.Stop();            var s2 = Stopwatch.StartNew();            for (int i = 0; i < m; i++)            {                SumAsParallel(array);            }            s2.Stop();            Console.WriteLine("\n\n");            Console.WriteLine("============================================================");            Console.WriteLine("CALCULATE SUMMARY TEST");            Console.WriteLine("============================================================");            Console.WriteLine("Default Summary: " + ((double)(s1.Elapsed.TotalMilliseconds * 1000000) / m).ToString("0.00 ns"));            Console.WriteLine("Parallel Summary: " + ((double)(s2.Elapsed.TotalMilliseconds * 1000000) /m).ToString("0.00 ns"));            Console.WriteLine("\n\n");            Console.WriteLine("============================================================");            Console.WriteLine("Parallel ASOrder Test");            Console.WriteLine("============================================================");            var orderwords = from word in words.AsParallel().AsOrdered()                             where (word.Contains(‘a‘))                             select word;            var orderletterList = orderwords.ToList();            for (int i = 0; i < orderletterList.Count; i++)            {                Console.WriteLine(orderletterList[i]);            }            Console.WriteLine("\n\n");            Console.WriteLine("============================================================");            Console.WriteLine("Parallel OrderBy Test");            Console.WriteLine("============================================================");            var orderbywords = from word in words.AsParallel()                             where (word.Contains(‘a‘))                             orderby word ascending                             select word;            var orderbyletterList = orderbywords.ToList();            for (int i = 0; i < orderbyletterList.Count; i++)            {                Console.WriteLine(orderbyletterList[i]);            }            Console.ReadKey();        }    }}

測試結果:

測試其實運行過多次,關於單詞的測試LINQ的結果在32至34秒,PLINQ大概在16至19秒,大約有50%的提升。

關於PLINQ中的資料分區

PLINQ使用多個任務對同一個資料來源進行處理,然後匯總,使得效率提高。但並存執行的任務應該處理資料的哪個部分,怎樣對資料進行合理的劃分,並且分配給任務是很重要的,它會嚴重的影響效率。但開發人員並不太可能去真正的控制PLINQ去採用哪種分區方式,瞭解一下它的內部機理在最佳化程式效能時會有一定的協助。

PLINQ中有四種資料的劃分方式:

  • 範圍劃分:用於可索引的資料來源,例如數組和列表。PLINQ會尋找資料來源的IList介面,如果找到了,它就會採取範圍據劃分方式,將資料分解為與可用的邏輯核心數目相等的分區。PLINQ可以確切的知道資料規模,而且可以直接存取其中的任意元素。
  • 資料區塊劃分:適用於任何資料來源,用於不可索引的資料,不同任務此時得到的是資料區塊,塊的大小可能不一樣。
  • 交錯式分區:這種方式對在資料來源頂部對資料項目進行處理的情況進行了最佳化。當查詢包括SkipWhile和TakeWhile時會採用這種方式。此時每個任務對應的是一小組資料(簡稱條紋)。任務通過簡單的計算可以判斷出資料對應的條紋,所以任務間並不需要同步。
  • 散列分區:主要針對資料比較進行了最佳化。它在資料和任務間建立了通道,帶有相同散列碼的資料項目會被發送到同一個任務中,這樣有可能的匹配便會在一個資料分區中,從而簡化了比較的過程,減少了不同任務間的資料共用。採用這種方式時分發資料時可能會有較大的開銷,但資料比較時效率會提高。

C# 並行編程 之 PLINQ 基本使用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.