我遇到了实现ContiguousChunkLazyEnumerator
类,该类由PLINQ使用(使用此迭代器执行块的遍历)。 MoveNext
方法使用线程安全访问源IEnumerator
(通过使用专用lock
),此外,它保存对内部缓冲区的访问结果。这是一段简短的代码:
lock (m_sourceSyncLock)
{
// Some .net stuff
try
{
for (; i < mutables.m_nextChunkMaxSize && m_source.MoveNext(); i++)
{
// Read the current entry into our buffer.
chunkBuffer[i] = m_source.Current;
}
}
// Some .net stuff
}
这样的迭代器将由工作线程使用(N个工作线程与同一迭代器一起工作)。但是我真的不理解这种并行方法的好处。在这种情况下使用
lock
应该可以消除任何性能上的好处。我的假设是,唯一工作线程的平等访问应该以相同的速度工作。 最佳答案
这是因为使用PLINQ针对项目的并发处理进行了优化,而不是针对项目的并发枚举进行了优化。
每个块都完成了繁重的lock
,因此多个线程将在块之间相互屈服。
当您拥有一个快速枚举的IEnumerable
时(例如,像List<T>
,实际上,对于List<T>
进行了内部优化,因此不是最佳示例),并且想要对结果进行一些缓慢的计算工作时,这确实很闪耀。
这段代码是关于创建分区数据,然后由多个线程使用的。尽管它是线程安全的,但不应认为它是最快的并发枚举。它针对数据局部性进行了优化。
关于c# - 在PLINQ中遍历块分区的实现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41672476/