任何人都可以/应该使用.NET 4.0中引入的类别Partitioner
的典型场景吗?何时使用分区类?
何时使用分区类?
回答
的Partitioner
类是用来做并行执行更多的矮胖。如果你有很多非常小的任务并行运行,那么为每个任务调用委托的开销可能会很高。通过使用Partitioner
,可以将工作负载重新排列为块,并且每个并行调用都可以在稍大的集合上工作。这个类抽象出这个特性,并且能够根据数据集和可用内核的实际情况进行分区。
示例:假设您想要像这样并行运行一个简单的计算。
Parallel.ForEach(Input, (value, loopState, index) => { Result[index] = value*Math.PI; });
这将调用Input中每个条目的委托。这样做会增加每个开销。通过使用Partitioner
,我们可以做这样的事情
Parallel.ForEach(Partitioner.Create(0, Input.Length), range => {
for (var index = range.Item1; index < range.Item2; index++) {
Result[index] = Input[index]*Math.PI;
}
});
这将减少所调用的数量,因为每个调用将在更大的一组工作。根据我的经验,这可以在非常简单的操作并行化时显着提升性能。
要并行化数据源上的操作,其中一个基本步骤是将源分区为可由多个线程同时访问的多个部分。当您编写并行查询或ForEach循环时,PLINQ和任务并行库(TPL)提供默认分区程序,这些分区程序可以透明地工作。对于更高级的场景,你可以插入你自己的分区器。
更多here:
我添加到:一般来说*你*不使用它。 PLINQ的确如此,你可能会逃脱默认分区。 – 2010-10-27 09:51:24
如Brian Rasmussen所建议的,范围分区是一种在CPU密集型工作时应该使用的分区类型,往往很小(相对于虚拟方法调用),必须处理许多元素,并且当涉及到每个元素的运行时间时,大多是不变的。
应该考虑的另一种类型的分区是块分区。这种类型的分区也被称为负载平衡算法,因为工作线程在很多工作要做的时候很少会闲置 - 这不是范围分区的情况。
当工作有一些等待状态时,应该使用块分区,每个元素往往需要更多的处理,或者每个元素可能有明显不同的工作处理时间。
这样做的一个例子可能是读入内存并处理大小不同的100个文件。 1K文件的处理时间比1mb文件少得多。如果为此使用范围分区,则某些线程可能会闲置一段时间,因为它们碰巧处理较小的文件。
与范围分区不同,无法指定每个任务要处理的元素数 - 除非您编写自己的定制分区程序。使用块分区的另一个缺点是,当它返回到另一个块时可能会有一些争用,因为在此时使用了排它锁。所以,很显然,一个块分区不应该用于短时间的CPU密集型工作。
默认块分区程序以每个块的块大小为1个元素开始。在每个线程处理三个1元素块之后,块大小每块增加到2个元素。每个线程处理了三个2元素块后,块大小再次递增为每个块3个元素,依此类推。至少这是按照 Dixin Yan(参见块分区部分)为Microsoft工作的方式。
顺便说一下,他博客中的可视化工具好像是Concurrency Visualizer profile tool。 docs for this tool声称它可用于定位性能瓶颈,CPU利用率低下,线程争用,跨核心线程迁移,同步延迟,DirectX活动,重叠I/O区域以及其他信息。它提供了图形,表格和文本数据视图,可以显示应用程序中的线程与整个系统之间的关系。
其他资源:
- 1. 使用#define来区分调用类
- 2. 区分使用SFINAE和void_t的类型
- 3. 使用分区
- 4. MVC3何时使用区域?
- 5. 如何使用Hive HQL创建分区表'像'未分区表?
- 6. TimeZone - 如何区分GMT时区和无法识别的时区?
- 7. 如何使用包名来区分grails中的类?
- 8. 用于GPT分区表的启动分区类型
- 9. 使用瑟茜为普通类(不区分类别)
- 10. 使用scikit-learn来区分类似的类别
- 11. 如何在使用MVC时刷新特定分区
- 12. 如何区分使用GitExtensions时的当前文件
- 13. 如何在使用scanf和'%d'时区分int和char
- 14. Highcharts如何使用时间百分比区域
- 15. 如何区分使用execvp时的执行情况?
- 16. 如何区分使用运算符时的读/写操作[]
- 17. 如何在使用显示时显示分区:无
- 18. 如何在使用pinMode时区分模拟和数字引脚?
- 19. 如何使用Spring RequestMapping区分域名
- 20. 如何使用LINQ来区分列表?
- 21. 如何在LINQ中使用分区?
- 22. 如何使用angularjs区分HTML选项?
- 23. 蟒蛇:使用分区(”“)
- 24. 使用分区由SQL Server
- 25. 使用JavaScript区分页面
- 26. 如何区分类的实例?
- 27. 如何区分类“ClassA”和“Module :: ClassA”?
- 28. 如何区分对象类型c#
- 29. 如何区分同类输入?
- 30. 如何区分USB设备类型?
Partitioner.Create()的默认rangeSize是1。因此,这两个代码示例的分区是相同的。除非Partitioner.Create(0,Input.Length,i);其中i> 1,它仍然具有相同数量的线程。 – Pingpong 2014-01-24 15:31:28