Подтвердить что ты не робот

Ожидание нескольких фьючерсов?

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

Есть ли хороший способ реализовать это с помощью асинхронной/будущей парадигмы в С++ 11?

На первый взгляд, он выглядит прямо, вы просто создаете несколько задач с помощью:

std::future<T> result = std::async(...);

и затем запустите result.get(), чтобы получить асинхронный результат задачи.

Однако проблема заключается в том, что будущие объекты должны храниться в какой-то очереди и их следует ждать один за другим. Тем не менее, возможно повторять итерации над будущими объектами снова и снова, проверяя, готов ли какой-либо из них, но это нежелательно из-за ненужной загрузки ЦП.

Возможно ли каким-то образом ожидать любого будущего от данного набора, чтобы быть готовым и получить его результат?

Единственный вариант, о котором я могу думать до сих пор, - это подход старой школы без асинхронного/будущего. В частности, нереста нескольких рабочих потоков и в конце каждого потока нажимают свой результат в защищенную mutex очередь, уведомляя поток ожидания через переменную условия, что очередь была обновлена ​​с большим количеством результатов.

Есть ли еще лучшее решение с асинхронным/будущим?

4b9b3361

Ответ 1

Поддержка потоков в С++ 11 была всего лишь первым проходом, а пока std::future скалы, она еще не поддерживает многократное ожидание.

Вы можете подделать его относительно неэффективно. Вы создаете вспомогательный поток для каждого std::future (ouch, очень дорого), а затем собираете их "этот future готов" в синхронную очередь сообщений с одним потребителем с несколькими производителями, а затем настраиваете потребительскую задачу, которая отправляет тот факт, что данный std::future готов.

std::future в этой системе не добавляет много функциональности, и задачи, которые прямо указывают, что они готовы, и вставляют свой результат в указанную выше очередь, будут более эффективными. Если вы пройдете этот маршрут, вы можете написать оболочку, соответствующую шаблону std::async или std::thread, и вернуть объект std::future, который представляет сообщение очереди. Это в основном предполагает повторную реализацию библиотеки concurrency.

Если вы хотите остаться с std::future, вы можете создать shared_future s, и каждая зависимая задача зависит от набора shared_future s: т.е. делать это без центрального планировщика. Это не позволяет такие вещи, как сообщения о прерывании/завершении работы, которые я считаю важными для надежной многопоточной системы задач.

Наконец, вы можете подождать С++ 2x, или всякий раз, когда concurrency TS складывается в стандарт, чтобы решить проблему для вас.

Ответ 2

Вы можете создать все фьючерсы "поколения 1" и дать все эти фьючерсы вашим задачам поколения 2, которые сами будут ждать их ввода.