Индекс потока в PLINQ Query? - PullRequest
       5

Индекс потока в PLINQ Query?

1 голос
/ 02 ноября 2010

Есть ли способ передать «индекс» потока запроса PLINQ в один из его операторов, например, в Select?

Исходным фоном является то, что у меня есть запрос PLINQ, который выполняет некоторую десериализацию, метод десериализации использует структуру (вероятно, массив) для передачи данных другому методу:

      ParallelEnumerable.Range(0, nrObjects)
        .WithDegreeOfParallelism(8)
        .Select(i => this.Deserialize(serializer, i, arrays[threadIndex]))
        .ToList();

(threadIndex - этоновая переменная, которую я хотел бы)

Если бы я знал индекс потока, я мог бы создать 8 из этих массивов заранее (даже если все они могут не использоваться) и использовать их повторно.Метод десериализации может быть вызван миллионы раз, поэтому каждая маленькая оптимизация имеет значение.

Ответы [ 3 ]

1 голос
/ 02 ноября 2010

Re thread index;обратите внимание, что степень параллелизма составляет (IIRC) только число максимум используемых потоков; не может использовать это число.Если полагаться на threadIndex так, как вы описываете, это может означать, что вы могли бы на самом деле иметь доступ только к arrays[0].Короче говоря, нет: я так не думаю.

Вы можете , однако получите индекс item ;так что если это то, что вы имеете в виду, просто:

.Select((value, itemIndex) => this.Deserialize(
     serializer, i, arrays[itemIndex])).ToList();

Это звучит (комментарии) как намерение для получения рабочего буфера;в этом случае я бы (и действительно, do ) оставил несколько удобных буферов в контейнере (с синхронизированным доступом и т. д.), то есть

  • попытался бы получить существующий буфер изконтейнер (синхронизированный)
  • , если не найден, создайте новый буфер
  • (выполнить работу)
  • возврат / добавление буфера в контейнер (синхронизированный)

Как правило, это будет очень быстро (намного быстрее, чем выделение буфера за одну итерацию)

0 голосов
/ 07 ноября 2010

Я бы порекомендовал использовать Parallel.ForEach, который предлагает перегрузку, которая позволяет распределять (и очищать) локальные , которые будут передаваться в один параллельный экземпляр цикла за раз.Я использовал этот подход для обработки больших наборов данных изображения, где мне требуются буферы для различных этапов процесса.

0 голосов
/ 02 ноября 2010

Вы можете создать ConcurrentBag целых чисел, а затем извлечь из него, прежде чем десереализацию использовать в качестве индекса, а затем вернуть после.Каждый поток будет занимать один элемент массива за раз.

Рассмотрите возможность использования Параллельный класс .Это более уместно, когда речь идет о массивах.Существуют ограничения на индексированные версии Select, если вы используете ParallelEnumerable (Не в вашем случае, но будьте осторожны)

...