前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C#:数据并行

C#:数据并行

原创
作者头像
sherlock99
发布2018-07-24 22:01:31
7290
发布2018-07-24 22:01:31
举报
文章被收录于专栏:日常工作总结

数据并行是指对源集合或数组中的元素同时(即并行)执行相同操作的情况。

简单的并行for循环

代码语言:javascript
复制
 Parallel.For(0, length, i =>
{
       //do something about i
});

并行foreach循环

代码语言:javascript
复制
            //  Method signature: Parallel.ForEach(IEnumerable<TSource> source, Action<TSource> body)
            Parallel.ForEach(files, currentFile =>
            {
                // The more computational work you do here, the greater 
                // the speedup compared to a sequential foreach loop.
                string filename = System.IO.Path.GetFileName(currentFile);
                System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(currentFile);

                bitmap.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
                bitmap.Save(System.IO.Path.Combine(newDir, filename));

                // Peek behind the scenes to see how work is parallelized.
                // But be aware: Thread contention for the Console slows down parallel loops!!!
                Console.WriteLine("Processing {0} on thread {1}", filename,
                                    Thread.CurrentThread.ManagedThreadId);

            } //close lambda expression
                 ); //close method invocation

并行时的break和continue

在使用并行for的时候,普通的break和continue在这里并没有太大作用。

取而代之的是stop和break方法。

在 Action<int, ParallelLoopState>等这样的action中,使用如下的代码可以实现stop和break:

代码语言:javascript
复制
            Parallel.For(0, source.Length, (i, loopState) =>
            {
                loopState.Stop();
            } // Close lambda expression.
            ); // Close Parallel.For

代码语言:javascript
复制
            Parallel.For(0, source.Length, (i, loopState) =>
            {
                double d = Compute(source[i]);
                results.Push(d);
                if (d > .2)
                {
                    // Might be called more than once!
                    loopState.Break();
                    Console.WriteLine("Break called at iteration {0}. d = {1} ", i, d);
                    Thread.Sleep(1000);
                }
            });

使用Stop的时候,系统将通知其他的并行线程在可能的时候尽快停止(不是保证立即停止,使用 ParallelLoopState.IsStopped检查是否已经停止)。

使用Break的时候,上面的0, source.Length(0到10000)一共被分成了4段:0 2500 5000 7500,当执行了break的时候,只有当前段会停止,其他段仍然会继续执行。

比如在0-2500段执行了break,不会影响到2500-5000段。

复杂一点的并行:带有线程局部变量

代码语言:javascript
复制
public static ParallelLoopResult For<TLocal>(int fromInclusive, int toExclusive, Func<TLocal> localInit, Func<int, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally);

下例中的subtotal即为线程中的局部变量:

代码语言:javascript
复制
            Parallel.For<long>(0, nums.Length, () => 0, (j, loop, subtotal) =>
            {
                subtotal += nums[j];
                return subtotal;
            },
                (x) => Interlocked.Add(ref total, x)
            );

fromInclusive: 开始索引(含)。 toExclusive: 结束索引(不含)。 localInit: 用于返回每个任务的本地数据的初始状态的函数委托。 body: 将为每个迭代调用一次的委托。 localFinally: 用于对每个任务的本地状态执行一个最终操作的委托。 类型参数: TLocal: 线程本地数据的类型。

第三个参数的类型为 Func<TResult>,其中 TResult 是将存储线程本地状态的变量的类型。 请注意,在此示例中使用了方法的泛型版本,并且类型参数为 long。类型参数告知编译器将要用于存储线程本地状态的临时变量的类型。 此示例中的 () => 0 表达式表示线程本地变量的初始值为零。如果是一个对象,是这样:() => new MyClass()。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档