Я наткнулся на реализацию ContiguousChunkLazyEnumerator
класс, который используется PLINQ (перемещение куска выполняется с помощью этого итератора). MoveNext
метод использует поточный безопасный доступ к источнику IEnumerator
(с использованием speficied lock
), кроме того, он сохраняет результаты доступа к внутреннему буферу. Это краткое фрагмент кода:Выполнение перемещения раздела chunk в PLINQ
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
должно привести к снижению производительности. Мое предположение заключается в том, что последовательный доступ только для рабочего потока должен работать с той же скоростью.
Я не понимаю вашего ответа. Я не вижу параллельных вычислений элементов коллекции (производительность блокировок убивает). Простая заметка - список будет обрабатываться разделом диапазона, а не секцией chunk. –
LmTinyToon
Да, я упомянул оптимизацию 'List'. Я имею в виду, что этот код предназначен для создания секционированных данных, которые затем будут потребляться несколькими потоками. Несмотря на то, что он является потокобезопасным, он не должен быть о самом быстром параллельном перечислении. Он оптимизирован для локальности данных. –
Stuart