Эффективная foreach дочерняя оценка параллельно

У меня есть список объектов, каждого с bool ShouldRun () метод на них.

Я в настоящее время выполняю итерации по списку объектов, и проверяю ShouldRun () на каждом объекте и называю Выполнение () на первом для возвращения true

foreach (child in Children)
{
   if (child.ShouldRun())
   {
      child.Run();
      break;
    }
 }

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

Однако я не могу думать о способе сделать это, которое удовлетворит эти условия:

1 Только выполняет один объект

2 не выполняют более поздний объект, если более ранний объект верен, или не закончил оценивать уже

3, Если все "более ранние" объекты возвратили false, и средний объект возвращает true, не ожидайте на более позднем объекте, чтобы закончить оценивать, потому что Вы знаете, что он ничего не может переопределить ранее.

Я думал о выполнении параллели, "где" linq запрашивают для получения всех объектов, что shouldRun () и затем сортировка, но это нарушит условие № 3

Идеи?

Вводная информация:

Система является для обобщенной робототехники системой AI.

Некоторые более высокие приоритетные задачи могут быть инициированы сразу известными переменными датчика, например: Я падаю, фиксирую его!

другие задачи могли бы быть в вычислительном отношении интенсивными (сделайте распознавание изображений со стороны камеры и приблизьтесь к видимым целям),

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

Некоторые сами задачи имеют дочерние задачи, который по существу собирается запустить этот процесс рекурсивно в подмножестве задач, и от задачи внука откажутся через цепочку

7
задан Jason Coyne 26 June 2010 в 22:33
поделиться

4 ответа

Я не гений PLINQ, но разве этого более простого ответа недостаточно?

var childToRun = Children.AsParallel().AsOrdered()
    .Where(x => x.ShouldRun()).FirstOrDefault();
childToRun.Run();  
3
ответ дан 7 December 2019 в 16:38
поделиться

Просто концепция того, как я бы попытался это сделать.

Выполнять все ShouldRun () параллельно. Поместите результаты в упорядоченный список вместе с элементами и индексами элементов (например, ShouldRun () третьего элемента заканчивается на false, список будет содержать что-то вроде: 2, false, item).

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

0
ответ дан 7 December 2019 в 16:38
поделиться

Вы должны иметь возможность выполнять параллельный выбор с помощью прикрепленные индексы, затем отсортируйте результат по индексу и выберите первый, который вернул истину . У меня нет IDE на этой машине, так что это не тестировалось, но что-то вроде:

var runnables = Children.AsParallel()
                        .Select(child, index => 
                                new { 
                                        Index = index, 
                                        ShouldRun = child.ShouldRun(),
                                        Child = child 
                                    })
                        .ToList(); //force evaluation
var firstRunner = runnables.OrderBy(r => r.Index)
                           .First(r => r.ShouldRun) //assuming at least one
                                   //else use FirstOrDefault and null-check
                           .Child;
firstRunner.Run();

edit: лучший запрос для первого участника -

var firstRunner = runnables.Where(r => r.ShouldRun) // less stuff to sort later
                           .OrderBy(r => r.Index)
                           .First(); // no need for predicate here anymore

edit2: однако это не удовлетворяет вашему условию №3.

0
ответ дан 7 December 2019 в 16:38
поделиться

Я озадачен тем, почему у вас есть флаг «ShouldRun» на каждом ребенке, вместо того, чтобы ранее поместить каждого ребенка, который вы бы пометили как «ShouldRun», в набор «RunThese».

Тогда вам нужно только спросить, равен ли размер набора RunThese нулю или нет, и если нет, запустите их все.

[Конечно, если вы собираетесь управлять ими, зачем даже отмечать/устанавливать их объединение? Вы можете просто запустить их, когда обнаружите, что должны их запускать. Если вы считаете, что логика ShouldRun стоит дорого, то разветвляйте ее в тот момент, когда у вас есть ребенок, чтобы решить, следует ли вам запускать ребенка.]

0
ответ дан 7 December 2019 в 16:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: