zoukankan      html  css  js  c++  java
  • c# 并行计算

    一、并行执行效率对比

    数据源

    Data = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    bool ShowProcessExecution = true;
    

    For循环

    DateTime dt1 = DateTime.Now;
    for(int i=0 ; i<data.Count;i++)
                {
                    Thread.Sleep(500);
                    if (ShowProcessExecution)
                        Console.WriteLine(data[i]);
                }
                DateTime dt2 = DateTime.Now;
                Console.WriteLine("普通For运行时常:{0}毫秒", (dt2 - dt1).TotalMilliseconds);
    

    Foreach

    DateTime dt1 = DateTime.Now;
                foreach(var i in data)
                {
                    Thread.Sleep(500);
                    if (ShowProcessExecution)
                        Console.WriteLine(data[i]);
                }         
                DateTime dt2 = DateTime.Now;
                Console.WriteLine("普通Foreach运行时常:{0}毫秒", (dt2 - dt1).TotalMilliseconds);
    

    并行For循环

                DateTime dt1 = DateTime.Now;         
                Parallel.For(0, data.Count, (i) =>
                    {
                        Thread.Sleep(500);
                        if (ShowProcessExecution)
                            Console.WriteLine(data[i]);
                    });
                DateTime dt2 = DateTime.Now;
                Console.WriteLine("并行For运行时常:{0}毫秒", (dt2 - dt1).TotalMilliseconds);
    

    并行Foreach

                DateTime dt1 = DateTime.Now;         
                Parallel.ForEach(data, (i) =>
                    {
                        Thread.Sleep(500);
                        if (ShowProcessExecution)
                            Console.WriteLine(data[i]);
                    });
                DateTime dt2 = DateTime.Now;
                Console.WriteLine("并行Foreach运行时常:{0}毫秒", (dt2 - dt1).TotalMilliseconds);
    

    效率对比

    普通For运行时常:5002毫秒
    普通Foreach运行时常:5000毫秒
    并行For运行时常:2009毫秒
    并行Foreach运行时常:1525毫秒

    二、并行中断

    Break中断

                Parallel.For(0, data.Count, (i, LoopState) =>
                    {
                        if (data[i] > 6)
                        {
                            LoopState.Break();
                        }
                        Thread.Sleep(500);
                        Console.WriteLine(data[i]);
                    });
                Console.WriteLine("Stop执行结束。");
    

    Stop中断

                Parallel.For(0, data.Count, (i, LoopState) =>
                    {
                        if (data[i] > 6)
                        {
                            LoopState.Stop();
                        }
                        Thread.Sleep(500);
                        Console.WriteLine(data[i]);
                    });
                Console.WriteLine("Stop执行结束。");
    

    三、为数组/集合添加项

    List是非线程安全的类,多线程操作的时候可能会出现报错

    可以使用System.Collections.Concurrent命名空间下

    ConcurrentQueue和ConcurrentStack线程安全的类来操作

                List<int> data = new List<int>();
                Parallel.For(0,Program.Data.Count, (i) =>
                {
                    if(Program.Data[i]%2==0)
                        data.Add(Program.Data[i]);
                });
                Console.WriteLine("执行完成For.");
    

    ConcurrentQueue

            ConcurrentStack<int> data = new ConcurrentStack<int>();
            Parallel.ForEach(Program.Data, (i) =>
            {
                if (Program.Data[i] % 2 == 0)
                    data.Push(Program.Data[i]);//将对象压入栈中
            });
            int R;
            while (data.TryPop(out R))//弹出栈顶对象
            {
                Console.WriteLine(R);
            }
            Console.WriteLine("执行完成ForEach.");
    

    ConcurrentStack

            ConcurrentStack<int> data = new ConcurrentStack<int>();
            Parallel.ForEach(Program.Data, (i) =>
            {
                if (Program.Data[i] % 2 == 0)
                    data.Push(Program.Data[i]);//将对象压入栈中
            });
            int R;
            while (data.TryPop(out R))//弹出栈顶对象
            {
                Console.WriteLine(R);
            }
            Console.WriteLine("执行完成ForEach.");
    

    四、并行运算中的局部变量

    Foreach局部变量

            long total = 0;
            // data数据源   int为 i 的类型, long 为 局部变量curNumber的类型       
            Parallel.ForEach<int,long>(data,      
                () => 0,                        // curNumber初始化0
                // 为每个迭代调用一次的委托,i是当前索引,LoopState是循环状态,curNumber为局部变量名
                (i, LoopState, curNumber) =>
                {
                    curNumber += i;              // 修改局部变量
                    return curNumber;            // 传递参数给下一个迭代
                },
                //对每个线程结果执行的最后操作,这里是将所有的结果相加
                (curNumber) => Interlocked.Add(ref total, curNumber)
                );
            Console.WriteLine(total);
        }
    

    For局部变量

            long total = 0;                 
            Parallel.For<long>(0,           // For循环的起点
                data.Count,                 // For循环的终点
                () => 0,                    // 初始化局部变量的方法(long),既为下面的curNumber的初值
                // 为每个迭代调用一次的委托,i是当前索引,LoopState是循环状态,curNumber为局部变量名
                (i, LoopState, curNumber) =>
                {
                    curNumber += data[i];    // 修改局部变量
                    return curNumber;        // 传递参数给下一个迭代
                },
    
                //对每个线程结果执行的最后操作,这里是将所有的结果相加
                (curNumber) => Interlocked.Add(ref total, curNumber)
                );
            Console.WriteLine(total);
    

    五、PLinq并行

            var source = Enumerable.Range(1, 10000);
            ConcurrentBag<int> concurrentBag = new ConcurrentBag<int>();
            //查询结果按source中的顺序排序
            var evenNums = from num in source.AsParallel().AsOrdered()
                          // where num % 100 == 0
                          orderby num
                           select num;
            evenNums.ForAll((e) => concurrentBag.Add(e));
            //ForAll的使用
            var query = from num in source.AsParallel()
                        where num % 100 == 0
                        select num;
            query.ForAll((e) => concurrentBag.Add(e));
    
  • 相关阅读:
    EOF输入
    2019春总结作业
    2019春第二次课程设计报告
    2019春第一次课程设计实验报告
    2019第一次作业的项目模块结构介绍
    2019春第十二周作业
    2019春第十一周作业
    2019春第十周作业
    2019春第九周作业
    2019春第八周作业
  • 原文地址:https://www.cnblogs.com/tangpeng97/p/13703824.html
Copyright © 2011-2022 走看看