PFX/PLINQ 的优化很复杂。但是,这是基本图片...
输入端优化:
PLINQ 具有三种用于将输入元素分配给线程的分区策略:
Strategy Element allocationRelative performance
Chunk partitioning Dynamic Average
Range partitioning Static Poor to excellent
Hash partitioning Static Poor
对于需要比较元素( 、 等)的查询运算符,GroupBy
PLINQJoin
总是GroupJoin
选择相对低效的哈希分区,因为它必须预先计算每个元素的哈希码(以便具有相同代码的元素可以在同一线程上运行)。
对于所有其他查询运算符,您可以选择范围或块分区。默认情况下,如果输入序列是可索引的(如果它是并且数组继承自IList<T>
),PLINQ 将选择范围分区;否则它将选择块分区。
对于每个元素占用相似 CPU 时间的长序列,范围分区更快。否则,块分区会更快。
它们是如何工作的:
块分区的工作原理是让每个工作线程定期从输入序列中抓取小“块”元素进行处理。PLINQ 首先分配非常小的块,然后随着查询的进行增加这个数量;这确保了小序列被有效地并行化,并且大序列不会出现过多的“往返”。如果一个工作线程碰巧很快完成了它的工作,它最终会得到更多的块。该系统使每个线程保持同样繁忙,并且机器的核心“平衡”。这种方法的缺点是从共享输入序列中获取元素需要锁定,这会增加开销。
范围分区绕过了正常的输入端枚举,并为每个工作线程预先分配了相等数量的元素,从而避免了输入序列的争用。如果一个线程使用此方法提前完成,它将处于空闲状态,直到其他线程完成。
平行For
和Foreach
:
默认情况下,for For
/ Foreach
loops PLINQ 将使用范围分区。
我希望这有帮助。