我遇到了实现 ContiguousChunkLazyEnumerator
类,它被 PLINQ 使用( block 的遍历是用这个迭代器执行的)。 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
每个 block 都完成,因此多个线程将在 block 之间相互让步。
当你有一个 IEnumerable
时,这真的很棒可以快速枚举(例如 List<T>
,实际上,List<T>
有内部优化,所以不是最好的例子),并希望对结果进行一些缓慢的计算工作。
这段代码是关于创建分区数据,然后由多个线程使用。虽然它是线程安全的,但它不应该是最快的并发枚举。它针对数据局部性进行了优化。
关于c# - PLINQ遍历chunk分区的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41672476/