我遇到了实现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/

10-10 08:52