1. 程式人生 > 實用技巧 >(精華)2020年9月7日 C#基礎知識點 PLinq的使用

(精華)2020年9月7日 C#基礎知識點 PLinq的使用

(精華)2020年9月7日 C#基礎知識點 PLinq的使用

Parallel的基本使用

private static void Run1()
{<!-- -->
    Console.WriteLine("任務1:3s");
    Thread.Sleep(3000);
}

private static void Run2()
{<!-- -->
    Console.WriteLine("任務2:5s");
    Thread.Sleep(5000);
}

private static void ParallerTest01()
{<!-- -->
    var watch = Stopwatch.StartNew();
    watch.Start();
    Run1();
    Run2();
    Console.WriteLine("序列耗時:{0}", watch.ElapsedMilliseconds);

    watch.Restart();
    Parallel.Invoke(Run1, Run2);
    Console.WriteLine("並行耗時:{0}", watch.ElapsedMilliseconds);
    Console.Read();
}

private static void ParallerTest02()
{<!-- -->
    for (var j = 1; j < 5; j++)
    {<!-- -->
        Console.WriteLine("第{0}次迴圈", j);

        #region 並行
        var bag = new ConcurrentBag<int>();
        var watch = Stopwatch.StartNew();
        watch.Start();
        Parallel.For(0, 20_000_000, i =>
        {<!-- -->
            bag.Add(i);
        });
        Console.WriteLine($"並行耗時:{watch.ElapsedMilliseconds}");
        #endregion

        #region 序列
        var bag1 = new ConcurrentBag<int>();
        watch = Stopwatch.StartNew();
        watch.Start();
        for (var i = 0; i < 20_000_000; i++)
        {<!-- -->
            bag1.Add(i);
        }

        Console.WriteLine($"序列耗時:{watch.ElapsedMilliseconds}");
        #endregion
    }
}

Parallel在linq中使用

 public partial class Program
{<!-- -->
    private static void 01()
    {<!-- -->
        var students = new ConcurrentDictionary<int, Student>();
        // 並行生成1000萬條資料
        Parallel.For(0, 10_000_000, (i) =>
        {<!-- -->
            var single = new Student
            {<!-- -->
                Id = i,
                Name = "name" + i,
                Age = i % 100,
                CreateTime = DateTime.Now.AddSeconds(i)
            };
            students.TryAdd(i, single);
        });
        Console.WriteLine("資料已生成");

        // PLINQ查詢
        var watch = new Stopwatch();
        watch.Start();
        var query1 = (from n in students.Values.AsParallel()
            where n.Age > 18 && n.Age < 80
            select n).ToList();

        watch.Stop();
        Console.WriteLine("PLINQ耗時:{0}", watch.ElapsedMilliseconds);

        // LINQ查詢
        watch.Restart();
        var query2 = (from n in students.Values
            where n.Age > 18 && n.Age < 80
            select n).ToList();

        watch.Stop();
        Console.WriteLine("LINQ耗時:{0}", watch.ElapsedMilliseconds);
    }

    private static void 02()
    {<!-- -->
        var students = new ConcurrentDictionary<int, Student>();
        Parallel.For(0, 10, (i) =>
        {<!-- -->
            var single = new Student
            {<!-- -->
                Id = i,
                Name = "name" + i,
                Age = i % 100,
                CreateTime = DateTime.Now.AddSeconds(i)
            };
            students.TryAdd(i, single);
        });
        Console.WriteLine("資料生成結束");

        // 測試PLNQ與LINQ查詢
        var query = from n in students.Values.AsParallel()
            select new {<!-- -->Name = n.Name, ThreadId = Thread.CurrentThread.ManagedThreadId};

        foreach (var o in query)
        {<!-- -->
            Console.WriteLine($"{o} - from ThreadId = {Thread.CurrentThread.ManagedThreadId}");
        }

        Console.WriteLine($"CurrentThreadId:{Thread.CurrentThread.ManagedThreadId}");
    }
}

PLINQ 執行MapReduce演算法
基本資訊

MapReduce(對映和規約)也稱 Map/Reduce 或 Map & Reduce,充分運用並行方式處理大資料集。基本思想是將資料處理問題分解為兩個獨立的且可並行執行的操作: Map 和 Reduce。

Map:對資料來源進行操作,為每個資料項計算出一個鍵值,執行的結果是一個鍵-值對的集合,並且根據鍵分組。
Reduce:對Map產生的鍵-值對進行操作,對每個組進行規約操作,返回結果值(一個或多個)。

這裡寫圖片描述

程式示例:
一段文字,統計其中單詞的個數,資料量很少,只是演示PLINQ關於 MapReduce的執行方式。

第一步:建立了一個 單詞 和 數字1 組成的鍵-值對。這裡使用的是ILookup<>介面。
詳細參考:

https://msdn.microsoft.com/zh-cn/library/bb534291(v=VS.100).aspx

第二步:對鍵值對進行分組 select操作,並且選擇出Count大於1的word。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sample6_7_plinq_mapreduce
{<!-- -->
    class Program
    {<!-- -->
        public static string strTarget = @"English is a West Germanic language that was first spoken in 
early medieval England and is now a global lingua franca. 
It is an official language of almost 60 sovereign states, the most 
commonly spoken language in the United Kingdom, the United States, 
Canada, Australia, Ireland, and New Zealand, and a widely spoken 
language in countries in the Caribbean, Africa, and southeast Asia.
It is the third most common native language in the world, after Mandarin and Spanish.
It is widely learned as a second language and is an official language
of the United Nations, of the European Union, and of many other 
world and regional international organisations.";

        static void Main(string[] args)
        {<!-- -->
            string[] words = strTarget.Split(' ');

            ILookup<string, int> map = words.AsParallel().ToLookup(p => p, k => 1);

            var reduce = from IGrouping<string, int> wordMap
                         in map.AsParallel()
                         where wordMap.Count() > 1
                         select new {<!-- --> Word = wordMap.Key, Count = wordMap.Count() };

            foreach (var word in reduce)
                Console.WriteLine("Word: '{0}' : Count: {1}", word.Word, word.Count);

            Console.ReadLine();
        }
    }
}