并行编程(一)

   随着多核时代的到来,并行开发越来越展示出它的强大威力。在了解并行开发之前,我们先来了解两个法则“Amdahl”和“Gustafson”

 Amdahl

  amdahl法则,通过以下公式预测多处理器系统的最大理论性能提升(即加速比,speedup).这个公式也可以应用于运行多核微处理器上的并行算法

  最大加速比(倍数)=1/((1-p)+(p/N))

 其中:

  P 表示能够完全并行运行的代码比例

  N  表示可用的计算单元数(处理器或物理内核数)

  如果一个算法中总任务的50%(p=0.5)可以并行执行,那么在具有两个物理内核的微处理器上的最大加速比为1.33,如一个带有1000份任务的算法,其中有500份并行任务,如果串行版本需要消耗1000秒,那么并行的话就是750秒

  Gustafson 法则

  Gustafson 法则是在固定的时间i内可以执行的工作量

  总工作量(单元数)=s+(N*P)

  其中

  S表示一次执行完成的工作单元数

  P表示每一部分能够完全并行执行的工作单元数

  N表示可用的执行单元数(处理数或者物理内核数)

   如有 50个单元的顺序执行和50是个可以并行的工作单元,你的微处理器是8核的

  那么 总工作量(单元数)=50+(8*50)=450 单元的工作量

通过上面两个法则,我们就知道并行编程的重要性,下面我们用代码测试一下

   

class Program
    {
        static void Main(string[] args)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            Run1();
            Run2();
            stopwatch.Stop();
            Console.WriteLine("串行执行所需要的时间{0}", stopwatch.ElapsedMilliseconds);
            stopwatch.Restart();
            Parallel.Invoke(Run1,Run2);
            stopwatch.Stop();
            Console.WriteLine("串行执行所需要的时间{0}", stopwatch.ElapsedMilliseconds);
            Console.ReadLine();
        }

        static void Run1()
        {
            Thread.Sleep(5000);
            Console.WriteLine("任务一");
        }
        static void Run2()
        {
            Console.WriteLine("任务二");
            Thread.Sleep(5000);
        }
    }

结果

 

可想而知我们的时间就减少了一半,是不是很开心,下面我们对C# 提供给我们的类进行来解释一下

Parallel类

      在这里我要说一下parallel   提供的是任务而不是线程,任务是架构在线程之上的,任务通过底层算法会根据你电脑的现在状况来选择cup核来为你工作

  在Parallel下面有三个常用的方法invoke,for和forEach。

  1. Invoke 是执行并行方法

       可以传递void返回值得函数

  

Parallel.Invoke(Run1,Run2);

  也可以传递 lambda表达式,通过Parallel.Invoke 编写的并行执行的代码一定不能依赖于特定的执行顺序,如果需要以特定的执行顺序允许并发代码,后面章节中还会使用高级的东西

 Parallel.Invoke(()=>{ Run1(); },Run2);

   2.Parallel.For

 这个函数对一下数据的检索和添加非常好,

class Program
    {
        static void Main(string[] args)
        {
            List<int> excel1=null;
            List<int> excel2=null;
            //并行读出两个表的而数据
            Parallel.Invoke(() => { excel1 = GetExcel1(); }, () => { excel2 = GetExcel2();});

            //通过并行方式快速将excel2中符合添加的数据加载到excel1表中
            Parallel.For(0,excel2.Count,(i)=>{
                if(excel2[i]%2==0)
                { 
                    excel1.Add(excel2[i]);
                }
            });

        }
     
        static List<int> GetExcel1()
        {
            Thread.Sleep(5000);
            Console.WriteLine("任务一");
            List<int> listExcel1 = new List<int>();
            for (int i = 0; i < 100; i++)
            {
                listExcel1.Add(i);
            }
            return listExcel1;
        }
        static List<int> GetExcel2()
        {
            Thread.Sleep(5000);
            Console.WriteLine("任务二");
            List<int> listExcel1 = new List<int>();
            for (int i = 100; i < 1000; i++)
            {
                listExcel1.Add(i);
            }
            return listExcel1;
        }
    }

3. Parallel.ForEach

  对应foreach是分片的,他的运用场合也挺多的,自己慢慢去理解吧

Parallel.ForEach(Partitioner.Create(0, 3000000), i =>
            {
               
                    Console.WriteLine("开始{0}-------结束{1}",i.Item1,i.Item2);
               
            });

原文地址:https://www.cnblogs.com/xuehaiyiye/p/5610514.html