《C#并发编程经典实例》学习笔记—3.1 数据的并行处理
程序员文章站
2023-11-09 21:55:34
问题 有一批数据,需要对每个元素进行相同的操作。该操作是计算密集型的,需要耗费一定的时间。 解决方案 常见的操作可以粗略分为 计算密集型操作 和 IO密集型操作。计算密集型操作主要是依赖于CPU计算,所以可以最大限度利用多核CPU的并行操作非常适合计算密集型操作。图像操作是比较常见的计算密集型操作, ......
问题
有一批数据,需要对每个元素进行相同的操作。该操作是计算密集型的,需要耗费一定的时间。
解决方案
常见的操作可以粗略分为 计算密集型操作 和 io密集型操作。计算密集型操作主要是依赖于cpu计算,所以可以最大限度利用多核cpu的并行操作非常适合计算密集型操作。图像操作是比较常见的计算密集型操作,图像操作一般是借助矩阵存储图像数据,该书作者就举了矩阵旋转为例。
思路是借助parallel.foreach实现并行操作。
伪代码如下
void rotatematrices(ienumerable<matrix> matrices, float degrees) { parallel.foreach(matrices, matrix => matrix.rotate(degrees)); }
当前循环处理无效值时,可能需要停止该循环,实现如下
void invertmatrices(ienumerable<matrix> matrices) { parallel.foreach(matrices, (matrix, state) => { if (!matrix.isinvertible) state.stop(); else matrix.invert(); }); }
而如果是想要取消整个并行循环,则需要借助cancellationtoken,即可以有一个取消按钮,点击取消按钮,应取消循环操作。
void rotatematrices(ienumerable<matrix> matrices, float degrees, cancellationtoken token) { parallel.foreach(matrices, new paralleloptions { cancellationtoken = token }, matrix => matrix.rotate(degrees)); }
另:当一个全局变量在并行循环内部被操作时,则需要考虑多进程共享状态。因为并行循环的每个循环很可能在不同的线程中运行。
// 注意,这不是最高效的实现方式。 // 只是举个例子,说明用锁来保护共享状态。 int invertmatrices(ienumerable<matrix> matrices) { object mutex = new object(); int noninvertiblecount = 0; parallel.foreach(matrices, matrix => { if (matrix.isinvertible) { matrix.invert(); } else { lock (mutex) { ++noninvertiblecount; } } }); return noninvertiblecount; }
在 《c#并发编程经典实例》学习笔记-第一章并发编程概述 - repeatedly - 博客园 ,我提到了并行操作的两种方式,一种是parallel,另一种是plinq(parallel linq)。所以上述操作也可以使用plinq实现。
两者是有区别的,区别如下:
parallel 类和 plinq 之间有一个区别:plinq 假设可以使用计算机内所有的cpu 核,而 parallel 类则会根据 cpu 状态的变化动态地调整。
相信对c#语法比较熟悉的应该能看出来,parallel.foreach是并行foreach循环,那么并行for循环对应的方法是什么呢?是parallel.for 方法。
下一篇: mac上配置Android环境变量的方法
推荐阅读
-
《C#并发编程经典实例》学习笔记—3.1 数据的并行处理
-
《C#并发编程经典实例》学习笔记—2.1 暂停一段时间
-
《C#并发编程经典实例》读书笔记-关于并发编程的几个误解
-
《C#并发编程经典实例》学习笔记—2.2 返回完成的任务
-
《C#并发编程经典实例》学习笔记-进程(process)和线程(thread)
-
《C#并发编程经典实例》学习笔记—2.9 处理 async void 方法的异常
-
《C#并发编程经典实例》学习笔记—2.8 处理 async Task 方法的异常
-
《C#并发编程经典实例》学习笔记-第一章并发编程概述
-
《C#并发编程经典实例》学习笔记-第一章并发编程概述
-
《C#并发编程经典实例》学习笔记—2.5 等待任意一个任务完成 Task.WhenAny