文档章节

并行开发——第一篇 Parallel的使用

厮以为
 厮以为
发布于 2014/11/14 12:01
字数 1125
阅读 68
收藏 1

在.net 4.0中,微软给我们提供了一个新的命名空间:System.Threading.Tasks。

一: Parallel的使用

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

1:  Parallel.Invoke

    这是最简单,最简洁的将串行的代码并行化

class Program
{
    static void Main(string[] args)
    {
        var watch = Stopwatch.StartNew();

        watch.Start();

        Run1();

        Run2();

        Console.WriteLine("我是串行开发,总共耗时:{0}\n", watch.ElapsedMilliseconds);

        watch.Restart();

        Parallel.Invoke(Run1, Run2);

        watch.Stop();

        Console.WriteLine("我是并行开发,总共耗时:{0}", watch.ElapsedMilliseconds);

        Console.Read();
    }

    static void Run1()
    {
        Console.WriteLine("我是任务一,我跑了3s");
        Thread.Sleep(3000);
    }

    static void Run2()
    {
        Console.WriteLine("我是任务二,我跑了5s");
        Thread.Sleep(5000);
    }
}

在这个例子中可以获取点信息:

尽可能的避免子任务之间的依赖性,因为子任务是并行执行,所以就没有谁一定在前,谁一定在后的规定了。

2:Parallel.for

 我们知道串行代码中也有一个for,但是那个for并没有用到多核,而Paraller.for它会在底层根据硬件线程的运行状况来充分的使用所有的可

利用的硬件线程,注意这里的Parallel.for的步行是1。这里我们来演示一下,向一个线程安全的集合插入数据,当然这个集合采用原子性来实现线程同步,比那些重量级的锁机制更加的节省消耗。

class Program
    {
        static void Main(string[] args)
        {
            for (int j = 1; j < 4; j++)
            {
                Console.WriteLine("\n第{0}次比较", j);

                ConcurrentBag<int> bag = new ConcurrentBag<int>();

                var watch = Stopwatch.StartNew();

                watch.Start();

                for (int i = 0; i < 20000000; i++)
                {
                    bag.Add(i);
                }

                Console.WriteLine("串行计算:集合有:{0},总共耗时:{1}", bag.Count, watch.ElapsedMilliseconds);

                GC.Collect();

                bag = new ConcurrentBag<int>();

                watch = Stopwatch.StartNew();

                watch.Start();

                Parallel.For(0, 20000000, i =>
                {
                    bag.Add(i);
                });

                Console.WriteLine("并行计算:集合有:{0},总共耗时:{1}", bag.Count, watch.ElapsedMilliseconds);

                GC.Collect();

            }
        }
    }

3:Parallel.forEach
    forEach的独到之处就是可以将数据进行分区,每一个小区内实现串行计算,分区采用Partitioner.Create实现。

class Program
    {
        static void Main(string[] args)
        {
            for (int j = 1; j < 4; j++)
            {
                Console.WriteLine("\n第{0}次比较", j);

                ConcurrentBag<int> bag = new ConcurrentBag<int>();

                var watch = Stopwatch.StartNew();

                watch.Start();

                for (int i = 0; i < 3000000; i++)
                {
                    bag.Add(i);
                }

                Console.WriteLine("串行计算:集合有:{0},总共耗时:{1}", bag.Count, watch.ElapsedMilliseconds);

                GC.Collect();

                bag = new ConcurrentBag<int>();

                watch = Stopwatch.StartNew();

                watch.Start();

                Parallel.ForEach(Partitioner.Create(0, 3000000), i =>
                {
                    for (int m = i.Item1; m < i.Item2; m++)
                    {
                        bag.Add(m);
                    }
                });

                Console.WriteLine("并行计算:集合有:{0},总共耗时:{1}", bag.Count, watch.ElapsedMilliseconds);

                GC.Collect();

            }
        }
    }

这里还是要说一下:Partitioner.Create(0, 3000000)。

第一:我们要分区的范围是0-3000000。

第二:我们肯定想知道系统给我们分了几个区? 很遗憾,这是系统内部协调的,无权告诉我们,当然系统也不反对我们自己指定分区个数,

        这里可以使用Partitioner.Create的第六个重载,比如这样:Partitioner.Create(0, 3000000, Environment.ProcessorCount),

下面分享下并行计算中我们可能有的疑惑?

<1> 如何中途退出并行循环?

      是的,在串行代码中我们break一下就搞定了,但是并行就不是这么简单了,不过没关系,在并行循环的委托参数中提供了一个ParallelLoopState,该实例提供了Break和Stop方法来帮我们实现。

Break: 当然这个是通知并行计算尽快的退出循环,比如并行计算正在迭代100,那么break后程序还会迭代所有小于100的。Stop:这个就不一样了,比如正在迭代100突然遇到stop,那它啥也不管了,直接退出

下面举个例子,当迭代到1000的时候退出循环

class Program
    {
        static void Main(string[] args)
        {
            var watch = Stopwatch.StartNew();

            watch.Start();

            ConcurrentBag<int> bag = new ConcurrentBag<int>();

            Parallel.For(0, 20000000, (i, state) =>
                  {
                      if (bag.Count == 1000)
                      {
                          state.Break();
                          return;
                      }
                      bag.Add(i);
                  });

            Console.WriteLine("当前集合有{0}个元素。", bag.Count);

        }
    }

<2> 并行计算中抛出异常怎么处理?(新手在编写并行程序的时候容易犯的错误)

 首先任务是并行计算的,处理过程中可能会产生n多的异常,那么如何来获取到这些异常呢?普通的Exception并不能获取到异常,然而为并行诞生的AggregateExcepation就可以获取到一组异常。

<3> 并行计算中我可以留一个硬件线程出来吗?

  默认的情况下,底层机制会尽可能多的使用硬件线程,然而我们使用手动指定的好处是我们可以在2,4,8个硬件线程的情况下来进行测量加速比

class Program
    {
        static void Main(string[] args)
        {
            var bag = new ConcurrentBag<int>();

            ParallelOptions options = new ParallelOptions();

            //指定使用的硬件线程数为1
            options.MaxDegreeOfParallelism = 1;

            Parallel.For(0, 300000, options, i =>
            {
                bag.Add(i);
            });

            Console.WriteLine("并行计算:集合有:{0}", bag.Count);

        }
    }


本文转载自:http://www.cnblogs.com/huangxincheng/archive/2012/04/02/2429543.html

共有 人打赏支持
厮以为
粉丝 31
博文 63
码字总数 84931
作品 0
深圳
架构师
私信 提问
5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq

5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编程 —— 第三...

雲霏霏
2014/09/28
0
0
Visual C++ 2010 新特性:并行计算

性能,永远是程序员要考虑的问题。在单核时代,甚至在双核(多核)时代,一般是通过改善客户使用的计算机性能来提升程序的性能,如增加服务器、内存,配置负载均衡等 手段来实现,我们称这个过...

红薯
2010/12/21
2.1K
10
OpenMP并行程序设计——for循环并行化详解

这篇OpenMP的for循环使用已经很详尽了,而且例子很好,就转载了,不再自己另开篇博客。 感谢作者。 转载请声明出处http://blog.csdn.net/zhongkejingwang/article/details/40018735 在C/C++...

sirius_0
04/23
0
0
JVM学习总结三——垃圾回收器

整两天再看调优分析的部分,发现实际运行环境下,还是要考虑配置垃圾回收器,所以这里就加一小章介绍一下。 首先来看一下HotSpot所支持回收期的关系图: 图中可以看到一共有7中垃圾回收器,以...

oO脾气不坏Oo
2014/03/06
0
0
在TensorFlow和PaddleFluid中使用多块GPU卡进行训练

前四篇文章我们介绍了 PaddleFluid 和 TensorFlow 的设计原理基本使用概念,分别通过在两个平台上实现完全相同的模型完成图像分类,语言模型和序列标注三个任务,了解我们的使用经验如何在两...

技术小能手
07/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

使用 React 和 Vue 创建相同的应用,他们有什么差异?

在工作中应用 Vue 之后,我对它有了相当深刻的理解。 不过,俗话说「外国的月亮比较圆」,我好奇「外国的」 React 是怎么样的。 我阅读了 React 文档并观看了一些教程视频,虽然它们很棒,但...

阿K1225
9分钟前
0
0
如何使用Kubernetes的configmap通过环境变量注入到pod里

在Kubernetes官网里,有这样一篇文章,提到了Kubernetes里的一个最佳实践就是把应用代码同配置信息分开,一种方式就是使用Kubernetes 1.2里引入的configmap概念。 https://kubernetes.io/bl...

JerryWang_SAP
25分钟前
0
0
2天闭门培训|以太坊智能合约从入门到实战(北京)

2天培训 16个课时 探寻技术原理,精通以太坊智能合约开发 以太坊智能合约是现在应用的最广泛的区块链应用开发方式,HiBlock区块链社区针对以太坊智能合约的学习特别推出2天闭门研修班,通过2...

HiBlock
27分钟前
0
0
限定某个目录禁止解析php,限制user_agent,php相关配置

11月20日任务 11.28 限定某个目录禁止解析php 11.29 限制user_agent 11.30/11.31 php相关配置 1.限定某个目录禁止解析php 核心配置文件内容 <Directory /data/wwwroot/www.123.com/upload> p...

hhpuppy
38分钟前
2
0
Spring的好文章

孤傲苍狼 https://www.cnblogs.com/xdp-gacl/p/4249939.html 跟我学spring http://jinnianshilongnian.iteye.com/blog/1413846 SpringIoc 和Spring Aop 代理模式: 静态代理 动态代理 cglib代......

wangwei2134
49分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部