首页 > 学院 > 开发设计 > 正文

C#并行编程-Parallel

2019-11-17 02:57:39
字体:
来源:转载
供稿:网友

C#并行编程-Parallel

菜鸟学习并行编程,参考《C#并行编程高级教程.PDF》,如有错误,欢迎指正。

目录

  • C#并行编程-相关概念

  • C#并行编程-Parallel

  • C#并行编程-Task

  • C#并行编程-并发集合

  • C#并行编程-线程同步原语

  • C#并行编程-PLINQ:声明式数据并行

TPL中引入了一个新命名空间System.Threading.Tasks,在该命名空间下Task是主类,表示一个类的异步的并发的操作,创建并行代码的时候不一定要直接使用Task类,在某些情况下可以直接使用Parallel静态类(System.Threading.Tasks.Parallel)下所提供的方法,而不用底层的Task实例。

Parallel.Invoke

试图将很多方法并行运行,如果传入的是4个方法,则至少需要4个逻辑内核才能足以让这4个方法并发运行,逻辑内核也称为硬件线程。

需要注意的是:1.即使拥有4个逻辑内核,也不一定能够保证所需要运行的4个方法能够同时启动运行,如果其中的一个内核处于繁忙状态,那么底层的调度逻辑可能会延迟某些方法的初始化执行。

2.通过Parallel.Invoke编写的并发执行代码一定不能依赖与特定的执行顺序,因为它的并发执行顺序也是不定的。

3.使用Parallel.Invoke方法一定要测量运行结果、实现加速比以及逻辑内核的使用率,这点很重要。

4.使用Parallel.Invoke,在运行并行方法前都会产生一些额外的开销,如分配硬件线程等。

好处:这是一种并行运行很多方法的简单方式,使用Parallel.Invoke,不需要考虑任务和线程的问题。

下面贴代码:

    class PRogram    {        private static List<Product> ProductList = null;        /*  coder:释迦苦僧         *  没有特定的执行顺序         *  示例中 基于电脑配置 采用了4个方法的并行编程         *  Parallel.Invoke 首先会尝试并行启动4个方法,充分利用一个或多个物理处理器所提供的多个逻辑内核         *  但是在实际的并行执行中,至少要有4个逻辑内核才能满足4个方法的并行运行         *  如果有个或者多个逻辑内核处于繁忙状态,那么底层的调度逻辑可能会延迟某些方法的初始化执行         *  通过Parallel.Invoke编写的并发执行代码一定不能依赖与特定的执行顺序,因为它的并发执行顺序也是不定的。         */        static void Main(string[] args)        {            ProductList = new List<Product>();            Thread.Sleep(3000);            Stopwatch swTask = new Stopwatch();            swTask.Start();            /*执行并行操作*/            Parallel.Invoke(SetProcuct1_500, SetProcuct2_500, SetProcuct3_500, SetProcuct4_500);            swTask.Stop();            Console.WriteLine("500条数据 并行编程所耗时间:" + swTask.ElapsedMilliseconds);            ProductList = new List<Product>();            Thread.Sleep(3000);/*防止并行操作 与 顺序操作冲突*/            Stopwatch sw = new Stopwatch();            sw.Start();            SetProcuct1_500();            SetProcuct2_500();            SetProcuct3_500();            SetProcuct4_500();            sw.Stop();            Console.WriteLine("500条数据  顺序编程所耗时间:" + sw.ElapsedMilliseconds);            ProductList = new List<Product>();            Thread.Sleep(3000);            swTask.Restart();            /*执行并行操作*/            Parallel.Invoke(() => SetProcuct1_10000(), () => SetProcuct2_10000(), () => SetProcuct3_10000(), () => SetProcuct4_10000());            swTask.Stop();            Console.WriteLine("10000条数据 并行编程所耗时间:" + swTask.ElapsedMilliseconds);            ProductList = new List<Product>();            Thread.Sleep(3000);            sw.Restart();            SetProcuct1_10000();            SetProcuct2_10000();            SetProcuct3_10000();            SetProcuct4_10000();            sw.Stop();            Console.WriteLine("10000条数据 顺序编程所耗时间:" + sw.ElapsedMilliseconds);            Console.ReadLine();        }        private static void SetProcuct1_500()        {            for (int index = 1; index < 500; index++)            {                Product model = new Product();                model.Category = "Category" + index;                model.Name = "Name" + index;                model.SellPrice = index;                ProductList.Add(model);            }            Console.WriteLine("SetProcuct1 执行完成");        }        private static void SetProcuct2_500()        {            for (int index = 500; index < 1000; index++)            {                Product model = new Product();                model.Category = "Category" + index;                model.Name = "Name" + index;                model.SellPrice = index;                ProductList.Add(model);            }            Console.WriteLine("SetProcuct2 执行完成");        }        private static void SetProcuct3_500()        {            for (int index = 1000; index < 2000; index++)            {                Product model = new Product();                model.Category = "Category" + index;                model.Name = "Name" + index;                model.SellPrice = index;                ProductList.Add(model);            }            Console.WriteLine("SetProcuct3 执行完成");        }        private static void SetProcuct4_500()        {            for (int index = 2000; index < 3000; index++)            {                Product model = new Product();                model.Category = "Category" + index;                model.Name = "Name" + index;                model.SellPrice = index;                ProductList.Add(model);            }            Console.WriteLine("SetProcuct4 执行完成");        }        private static void SetProcuct1_10000()        {            for (int index = 1; index < 20000; index++)            {                Product model = new Product();                model.Category = "Category" + index;                model.Name = "Name" + index;                model.SellPrice = index;                ProductList.Add(model);            }            Console.WriteLine("SetProcuct1 执行完成");        }        private static void SetProcuct2_10000()        {            for (int index = 20000; index < 40000; index++)            {                Product model = new Product();                model.Category = "Category" + index;                model.Name = "Name" + index;                model.SellPrice = index;                ProductList.Add(model);            }            Console.WriteLine("SetProcuct2 执行完成");        }        private static void SetProcuct3_10000()        {            for (int index = 40000; index < 60000; index++)            {                Product model = new Product();                model.Category = "Category" + index;                model.Name = "Name" + index;                model.SellPrice = index;                ProductList.Add(model);            }            Console.WriteLine("SetProcuct3 执行完成");        }        private static void SetProcuct4_10000()        {            for (int index = 60000; index < 80000; index++)            {                Product model = new Product();                model.Category = "Category" + index;                model.Name = "Name" + index;                model.SellPrice = index;                ProductList.Add(model);            }            Console.WriteLine("SetProcuct4 执行完成");        }    }    class Product    {        public string Name { get; set; }        public string Category { get; set; }        public int SellPrice { get; set; }    }
View Code

图中我们可以看出利用 Parallel.Invoke编写的并发执行代,它的并发执行顺序也是不定的。但是所执行的时间上比不采用并行编程所耗的时间差不多。

这是因为我们在并行编程中操作了共享资源 ProductList ,如果我把代码做出以下修改,采用并行编程的好处就显现出来了。

    class Program    {         /*  coder:释迦苦僧         *  没有特定的执行顺序         *  示例中 基于电脑配置 采用了4个方法的并行编程         *  Parallel.Invoke 首先会尝试并行启动4个方法,充分利用一个或多个物理处理器所提供的多个逻辑内核         *  但是在实际的并行执行中,至少要有4个逻辑内核才能满足4个方法的并行运行         *  如果有个或者多个逻辑内核处于繁忙状态,那么底层的调度逻辑可能会延迟某些方法的初始化执行         *  通过Parallel.Invoke编写的并发执行代码一定不能依赖与特定的执行顺序,因为它的并发执行顺序也是不定的。         */        static void Main(string[] args)        {             Thread.Sleep(3000);            Stopwatch swTask = new Stopwatch();            swTask.Start();            /*执行并行操作*/            Parallel.Invoke(SetProcuct1_500, SetProcuct2_500, SetProcuct3_500, SetProcuct4_500);            swTask.St
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表