8天玩轉並行開發——第三天 plinq的使用
相信在.net平臺下,我們都玩過linq,是的,linq讓我們的程式簡潔優美,簡直玩的是愛不釋手,但是傳統的linq只是序列程式碼,在並行的
年代如果linq不支援平行計算那該是多麼遺憾的事情啊。
當然linq有很多種方式,比如linq to sql ,xml,object 等等,如果要將linq做成並行還是很簡單的,這裡我就舉一個比較實際一點的例子,
我們知道為了更快的響應使用者操作,碼農們想盡了各種辦法,絞盡了腦汁,其中有一個辦法就是將資料庫資料預載入到記憶體中,然後透過各種
資料結構的手段來加速CURD,是的,比如一個排序地球人只能做到N(lgN),那麼如果我還想再快一點的話該怎麼辦呢?那麼現在的並行就能發
揮巨大的優勢,尤其是現在的伺服器配置都是在8個硬體執行緒的情況下,你簡直會狂笑好幾天啊,好,不亂扯了。
1:AsParallel(並行化)
下面我們模擬給ConcurrentDictionary灌入1500w條記錄,看看序列和並行效率上的差異,注意我的老爺機是2個硬體執行緒。
1 using System; 2 using System.Threading; 3 using System.Threading.Tasks; 4 using System.Diagnostics; 5 using System.Collections.Concurrent; 6 using System.Collections.Generic; 7 8 using System.Linq; 9 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 var dic = LoadData(); 15 16 Stopwatch watch = new Stopwatch(); 17 18 watch.Start(); 19 20 //序列執行 21 var query1 = (from n in dic.Values 22 where n.Age > 20 && n.Age 20 && n.Age LoadData() 43 { 44 ConcurrentDictionarydic = new ConcurrentDictionary (); 45 46 //預載入1500w條記錄 47 Parallel.For(0, 15000000, (i) => 48 { 49 var single = new Student() 50 { 51 ID = i, 52 Name = "hxc" + i, 53 Age = i % 151, 54 CreateTime = DateTime.Now.AddSeconds(i) 55 }; 56 dic.TryAdd(i, single); 57 }); 58 59 return dic; 60 } 61 62 public class Student 63 { 64 public int ID { get; set; } 65 66 public string Name { get; set; } 67 68 public int Age { get; set; } 69 70 public DateTime CreateTime { get; set; } 71 } 72 }
執行的結果還是比較震撼的,將近7倍,這是因為plinq的查詢引擎會盡量利用cpu的所有硬體執行緒。
2:常用方法的使用
orderby
有時候我們並不是簡單的select一下就ok了,可能需要將結果進行orderby操作,並行化引擎會把要遍歷的資料分割槽,然後在每個區上進行
orderby操作,最後來一個總的orderby,這裡很像演算法中的“歸併排序”。
1 using System; 2 using System.Threading; 3 using System.Threading.Tasks; 4 using System.Diagnostics; 5 using System.Collections.Concurrent; 6 using System.Collections.Generic; 7 8 using System.Linq; 9 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 var dic = LoadData(); 15 16 var query1 = (from n in dic.Values.AsParallel() 17 where n.Age > 20 && n.Age 23 { 24 Console.WriteLine(i.CreateTime); 25 }); 26 27 var query2 = (from n in dic.Values.AsParallel() 28 where n.Age > 20 && n.Age 34 { 35 Console.WriteLine(i.CreateTime); 36 }); 37 38 Console.Read(); 39 } 40 41 public static ConcurrentDictionaryLoadData() 42 { 43 ConcurrentDictionary dic = new ConcurrentDictionary (); 44 45 //預載入1500w條記錄 46 Parallel.For(0, 15000000, (i) => 47 { 48 var single = new Student() 49 { 50 ID = i, 51 Name = "hxc" + i, 52 Age = i % 151, 53 CreateTime = DateTime.Now.AddSeconds(i) 54 }; 55 dic.TryAdd(i, single); 56 }); 57 58 return dic; 59 } 60 61 public class Student 62 { 63 public int ID { get; set; } 64 65 public string Name { get; set; } 66 67 public int Age { get; set; } 68 69 public DateTime CreateTime { get; set; } 70 } 71 }
sum(),average()等等這些聚合函式的效果跟orderby型別一樣,都是實現了型別歸併排序的效果,這裡就不舉例子了。
3:指定並行度,這個我在前面文章也說過,為了不讓平行計算佔用全部的硬體執行緒,或許可能要留一個執行緒做其他事情。
1 var query2 = (from n in dic.Values.AsParallel() 2 .WithDegreeOfParallelism(Environment.ProcessorCount - 1) 3 where n.Age > 20 && n.Age
4: 瞭解ParallelEnumerable類
首先這個類是Enumerable的並行版本,提供了很多用於查詢實現的一組方法,截個圖,大家看看是不是很熟悉,要記住,他們都是並行的。
下面列舉幾個簡單的例子。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 ConcurrentBagbag = new ConcurrentBag (); 6 7 var list = ParallelEnumerable.Range(0, 10000); 8 9 list.ForAll((i) => 10 { 11 bag.Add(i); 12 }); 13 14 Console.WriteLine("bag集合中元素個數有:{0}", bag.Count); 15 16 Console.WriteLine("list集合中元素個數總和為:{0}", list.Sum()); 17 18 Console.WriteLine("list集合中元素最大值為:{0}", list.Max()); 19 20 Console.WriteLine("list集合中元素第一個元素為:{0}", list.FirstOrDefault()); 21 22 Console.Read(); 23 } 24 }
5: plinq實現MapReduce演算法
mapReduce是一個非常流行的程式設計模型,用於大規模資料集的平行計算,非常的牛X啊,記得mongodb中就用到了這個玩意。
map: 也就是“對映”操作,可以為每一個資料項建立一個鍵值對,對映完後會形成一個鍵值對的集合。
reduce:“化簡”操作,我們對這些巨大的“鍵值對集合“進行分組,統計等等。
具體大家可以看看百科:
下面我舉個例子,用Mapreduce來實現一個對age的分組統計。
using System; using System.Threading; using System.Threading.Tasks; using System.Diagnostics; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; class Program { static void Main(string[] args) { Listlist = new List () { new Student(){ ID=1, Name="jack", Age=20}, new Student(){ ID=1, Name="mary", Age=25}, new Student(){ ID=1, Name="joe", Age=29}, new Student(){ ID=1, Name="Aaron", Age=25}, }; //這裡我們會對age建立一組鍵值對 var map = list.AsParallel().ToLookup(i => i.Age, count => 1); //化簡統計 var reduce = from IGrouping singleMap in map.AsParallel() select new { Age = singleMap.Key, Count = singleMap.Count() }; ///最後遍歷 reduce.ForAll(i => { Console.WriteLine("當前Age={0}的人數有:{1}人", i.Age, i.Count); }); } public class Student { public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } public DateTime CreateTime { get; set; } } }
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3016/viewspace-2806291/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 5天玩轉C#並行和多執行緒程式設計 —— 第二天 並行集合和PLinqC#並行執行緒程式設計
- 5天玩轉C#並行和多執行緒程式設計 —— 第三天 認識和使用TaskC#並行執行緒程式設計
- 使用.NET並行任務庫(TPL)與並行Linq(PLINQ)充分利用多核效能並行
- C#並行,多執行緒程式設計並行集合和PLINQ的例項講解並行執行緒程式設計
- 玩轉iOS開發:iOS中的GCD開發(一)iOSGC
- 玩轉iOS開發:iOS中的GCD開發(三)iOSGC
- 玩轉iOS開發:iOS中的GCD開發(二)iOSGC
- iOS開發之玩轉字串iOS字串
- 玩轉iOS開發:iOS中的NSOperation開發(一)iOS
- 玩轉iOS開發:iOS中的NSOperation開發(二)iOS
- 並行開發基礎並行
- 使用Python玩轉WMI進行Win32api/com進行Windows程式設計開發PythonWin32APIWindows程式設計
- 玩轉iOS開發《建立CocoaPods開發庫》iOS
- 玩轉iOS開發:Touch ID整合iOS
- 並行執行 Job - 每天5分鐘玩轉 Docker 容器技術(134)並行Docker
- 玩轉 iOS 開發:NSURLSession 講解 (一)iOSSession
- 玩轉 React(二)- 新型前端開發方式React前端
- 使用Lccwin32進行MySQL開發。 (轉)Win32MySql
- 玩轉iOS開發:iOS 11 新特性《UICollectionView的拖放》iOSUIView
- Oracle的並行操作[轉]Oracle並行
- 玩轉iOS開發:iOS開發中的裝逼技術 – RunTime(一)iOS
- 玩轉iOS開發:iOS開發中的裝逼技術 – RunTime(二)iOS
- 玩轉iOS開發:iOS開發中的裝逼技術 - RunTime(二)iOS
- 玩轉iOS開發:iOS開發中的裝逼技術 - RunTime(一)iOS
- 玩轉iOS開發:實戰開發中的GCD Tips小技巧 (二)iOSGC
- 玩轉SSH埠轉發
- 玩轉 iOS 開發:整合 AliPay – 支付寶iOS
- 玩轉iOS開發:iOS 10 新特性《UserNotifications》iOS
- 玩轉 iOS 開發:整合 AliPay - 支付寶iOS
- 玩轉iOS開發:整合 WeChat SDK - 支付篇iOS
- 玩轉iOS開發:iOS 10 新特性《UIViewPropertyAnimator》iOSUIView
- 玩轉grub的開機引導(轉)
- 玩轉iOS開發:iOS 11 新特性《Layout的新特性》iOS
- 玩轉iOS開發:6.《Core Animation》CALayer的Specialized LayersiOSZed
- 玩轉iOS開發:iOS中的Socket程式設計(一)iOS程式設計
- 玩轉iOS開發:iOS中的Socket程式設計(三)iOS程式設計
- Oracle並行操作——淺議使用並行的時機Oracle並行
- 玩轉 iOS 開發:《iOS 設計模式 — 代理模式》iOS設計模式