Задача против Барьера

Поэтому моя проблема заключается в следующем: у меня есть список элементов для обработки, и я хотел бы обрабатывать элементы параллельно, а затем фиксировать обработанные элементы.

Класс барьера в C# позволит мне сделать это - я могу параллельно запускать потоки для обработки списка элементов, и когда вызывается SignalAndWait и все участники попадают в барьер, я могу зафиксировать обработанные элементы.

Класс Task также позволит мне сделать это - при вызове Task.WaitAll я могу дождаться завершения всех задач и зафиксировать обработанные элементы. Если я правильно понимаю, каждая задача будет выполняться в своем собственном потоке, а не в куче параллельных задач в одном потоке.

  1. Правильно ли мое понимание проблемы в обоих случаях?
  2. Есть ли какое-то преимущество между одним над другим?
  3. Есть ли способ гибридного решения лучше (барьер и задачи?).

2 ответа

Решение

Правильно ли мое понимание проблемы в обоих случаях?

Я думаю, у вас есть неправильное понимание Barrier учебный класс. Документы говорят:

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

Барьер - это примитив синхронизации. Сравнивая его с единицей работы, которая может быть вычислена параллельно, например Task не правильно

Барьер может сигнализировать всем потокам, чтобы они подождали, пока все остальные не завершили какую-либо работу, и проверили эту работу. Само по себе оно не имеет возможностей параллельных вычислений и никакой модели потоков.

Есть ли какое-то преимущество между одним над другим?

Что касается вопроса 1, вы видите, что это не имеет значения.

Есть ли способ гибридного решения лучше (барьер и задачи?).

В твоем случае я не уверен, что это вообще нужно. Если вы просто хотите параллельно выполнять вычисления с привязкой к ЦП для набора элементов, у вас есть Parallel.ForEach именно для этой цели. Он разделит перечислимое и вызовет их параллельно, и заблокирует, пока не будет вычислена вся коллекция.

Я не отвечаю прямо на ваш вопрос, потому что считаю, что работа с барьерами и задачами просто делает ваш код более сложным, чем он должен быть.

Я бы предложил для этого использовать Reactive Framework от Microsoft - NuGet "Rx-Main", поскольку он просто делает всю проблему очень простой.

Вот код:

var query =
    from item in items.ToObservable()
    from processed in Observable.Start(() => processItem(item))
    select new { item, processed };

query
    .ToArray()
    .Subscribe(processedItems =>
    {
        /* commit the processed items */
    });

Запрос превращает список элементов в наблюдаемый, а затем обрабатывает каждый элемент, используя Observable.Start(...), Это оптимально запускает новые темы по мере необходимости. .ToArray() берет последовательность отдельных результатов и изменяет ее в единый массив результатов. .Subscribe(...) Затем метод позволяет обрабатывать результаты.

Код намного проще, чем использование задач или барьеров.

Другие вопросы по тегам