分区是如何完成的,例如
Parallel.For(0, buffer.Length, (i)=> buffer[i] = 0);我的假设是,对于n核心机器,工作将被划分为n way,而n threads将执行工作负载。这意味着,例如,buffer.Length = 100 and n = 4, each thread will get 0-24, 25-49, 50-74, 75-99块。(100个元素数组是说明分区的一个示例,但请考虑一个包含数百万项的数组。)
这是否合理的假设?请讨论一下。
我注意到,在这个特定的场景中,Array.Clear(...)的执行速度要快得多。你怎么解释这件事?
发布于 2013-07-22 10:57:12
首先是简单的部分。一个100元素的数组是如此小,它可以很容易地适应一个核心的缓存。此外,清除数组相当于将内存区域设置为0,这是作为CPU命令可用的,因此尽可能快。
事实上,SSE命令和并行优化内存控制器意味着芯片组可能只使用一个CPU命令就可以并行清除内存。
另一方面,Parallel.For引入了一些开销。它必须对数据进行分区,创建适当的任务来处理它们,收集结果并返回最终结果。在Parallel.For下面,运行时必须将数据复制到每个核心,处理内存同步,收集结果等等。在您的示例中,这可能比内存位置零点所需的实际时间要大得多。
事实上,对于小规模的内存,很可能99.999%的开销是内存同步,因为每个内核都试图访问相同的内存页__。请记住,内存锁定在页面级别,您可以在一个4K内存页中安装2K 16位in。
至于PLINQ是如何安排任务的--根据您使用的运算符,使用了许多不同的分区方案。查看LINQ中的分区获得一个很好的介绍。在任何情况下,分区程序将尝试确定分区是否有任何好处,并且可能根本不对数据进行分区。
在您的示例中,分区程序可能会使用远程分区。您的有效负载只使用几个CPU周期,所以您所看到的只是分区、创建任务、管理同步和收集结果的开销。
一个更好的基准是在一个大数组上运行一些聚合,例如。计数和平均数等等。
https://stackoverflow.com/questions/17785049
复制相似问题