Правильное распараллеливание множества маленьких задач в методе с использованием C # .NET - PullRequest
0 голосов
/ 20 ноября 2018

Я реализую алгоритмы обработки изображений в C #, используя .NET Framework 4.72, и мне нужно уменьшить вычислительный код.В целом код является последовательным, но существует довольно много методов с параметрами, которые не зависят друг от друга.Например, это может быть что-то вроде

public void Algorithm(Object x, Object y) {    
    x = Filter(x);
    x = Morphology(x);
    y = Filter(y);
    y = Morphology(y);
    var z = Add(x,y);

    //Similar pattern of separate operation that are then combined.
}

Эти функции обычно занимают от 100 до 500 мс.Они могут быть распараллелены, и мой подход был примерно таким:

public void Algorithm(Object x, Object y) {  
    var xTask = Task.Run(() => {
        x = Filter(x);
        x = Morphology(x);
    });
    var yTask = Task.Run(() => {
        y = Filter(y);
        y = Morphology(y);
    });
    Task.WaitAll(xTask, yTask);
    var z = Add(x,y);
}

Кажется, работает, аналогичный фрагмент кода выполняется примерно вдвое быстрее.(Обратите внимание, что все это обернуто в другой Task.Run в функции самого верхнего уровня, поэтому я не await здесь.

Вопрос: Это правильный подход илиЕсть ли другой метод для распараллеливания множества небольших вызовов методов, который является более безопасным или эффективным?

Обновление: это не для распараллеливания обработки пакета изображений. Речь идет об обработке одного изображения как можно быстрее.

1 Ответ

0 голосов
/ 20 ноября 2018

Это достаточно верно - если вы можете обрабатывать свою рабочую нагрузку параллельно, тогда вам следует.Вам просто нужно быть в курсе, КОГДА ваша рабочая нагрузка может и должна быть параллельной - и когда это нужно выполнять по порядку.

Вам также необходимо учитывать стоимость создания новой задачи в сравнении с ее преимуществами (т. Е. Иногда избегать очень маленьких, очень быстрых задач).

Я настоятельно рекомендую вам создать дополнительныеметоды и коллекции для управления вашими задачами - когда они завершены и обрабатывают множество отдельных наборов параллельно.Как избежать блокировки, управлять общей памятью / переменными и т. Д. Например, обрабатываете ли вы когда-либо только одно изображение за раз, или вы можете начать обработку следующего, если у вас есть доступные ядра?

Вы должны быть очень осторожныс Task.WaitAll () - очевидно, в какой-то момент вам нужно объединить всю свою работу, но будьте осторожны, чтобы не блокировать и не блокировать другую работу.

Существует множество статей о различных шаблонах, которые вы можете использовать(Трубопровод звучит как хорошее совпадение).

Вот несколько примеров:

https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/tpl-and-traditional-async-programming

https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/potential-pitfalls-in-data-and-task-parallelism

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...