Параллельная обработка и разбиение списка на два - ускоряет ли это всю операцию? - PullRequest
3 голосов
/ 30 июня 2011

У меня есть операция, требующая проверки сотен тысяч матриц (2D-массивов int) до тех пор, пока не будет обработана каждая матрица или не выполнено определенное условие.По сути

For each matrix m in matricesList:
   if Function(m) returns true: exit
   else continue

Меня не интересует оптимизация функции ().Мне любопытно узнать, могу ли я разделить список матриц на два списка (по одному для каждого процессора) и выполнить операцию над ним.Если какой-либо процесс получает «True» в результате функции (), я бы хотел, чтобы оба процесса завершились и вернули true.

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

Я не уверен, что Function () вызовет проблемы с параллелизмом, но все, что он делает, это перебирает матрицу m и сравнивает еедругая матрица.Если искомое условие выполнено, возвращается значение true.

Ответы [ 2 ]

4 голосов
/ 30 июня 2011

До тех пор, пока сам метод Function () не генерирует слишком много конфликтов (блокировка ресурсов) - что, по вашему описанию, не похоже на это, а затраты на метод функции (в ресурсах) достаточно велики ( в основном это накладные расходы на разделение списка, создание дополнительных потоков и т. д., поэтому ваш выигрыш должен амортизировать эту стоимость), тогда да.

c # имеет несколько встроенных методов для обработки подобных ситуаций, вы можете использовать PLINQ

var y = matricesList.AsParallel().Where(m =>Function(m)).First();

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

Если вы хотите, чтобы PLINQ прерывался после одного совпадения, просто добавьте .Take (1) в

var y = matricesList.AsParallel().Where(m =>Function(m)).Take(1).First();

или библиотека параллельных задач

    Parallel.ForEach(matricesList, (m, parallelLoopState) =>
                            {
                                if (Function(m))
                                {
                                    parallelLoopState.Stop();
                                }
                            });

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

Оба метода будут обрабатывать правильное разбиение, используя правильное количество потоков для числа процессоров в системе и т. Д.

2 голосов
/ 30 июня 2011

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

Мы успешно использовали подобные приемы здесь, на сайте stackoverflow, хотя t является веб-сервером.мы ограничиваем параллельность до 2 потоков на запрос, что аккуратно вдвое сокращает время.В любом случае, из-за необходимости объединять результаты впоследствии использование большего количества протекторов было на самом деле контрпродуктивным - 2 было нашей приятной точкой.Немного, если вам не нужно комбинировать результаты каким-либо умным способом, вы можете немного увеличить параллелизм.

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