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

Почему я должен использовать std:: async?

Я пытаюсь изучить все варианты нового стандарта С++ 11 в глубину, используя std:: async и прочитав его определение, я заметил 2 вещи, по крайней мере, под linux с gcc 4.8.1:

  • он назвал async, но он получил действительно "последовательное поведение", в основном в строке, где вы называете будущее, связанную с вашей асинхронной функцией foo, программа блокирует до завершения выполнения foo.
  • это зависит от той же самой внешней библиотеки, что и другие, и более эффективных, неблокирующих решений, что означает pthread, если вы хотите использовать std::async, вам нужен pthread.

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

Я что-то упустил? Можете ли вы показать пример, который предоставляется для выполнения в async, без блокировки, способом?

4b9b3361

Ответ 1

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

Обратите внимание, что std::async можно запустить с помощью политик std::launch::async или std::launch::deferred. Если вы не укажете его, реализация может быть выбрана, и она вполне может предпочесть использовать отложенную оценку, которая приведет к тому, что вся работа будет выполнена, когда вы попытаетесь получить результат из будущего, в результате чего будет создан более длинный блок, Поэтому, если вы хотите убедиться, что работа выполняется асинхронно, используйте std::launch::async.

Ответ 2

  • он назвал async, но он получил действительно "последовательное поведение",

Нет, если вы используете политику std::launch::async, то она запускается асинхронно в новом потоке. Если вы не укажете политику, она может работать в новом потоке.

в основном в строке, где вы вызываете будущее, связанную с вашей асинхронной функцией foo, программа блокируется до выполнения foo.

Он блокируется только в том случае, если foo не завершен, но если он был запущен асинхронно (например, потому что вы используете политику std::launch::async), он может быть выполнен до того, как он вам понадобится.

  • это зависит от той же самой внешней библиотеки, что и другие, и более эффективных, неблокирующих решений, что означает pthread, если вы хотите использовать std:: async, вам нужен pthread.

Неправильно, его не нужно реализовывать с помощью Pthreads (а в Windows это не так, он использует функции ConcRT.)

в этот момент естественно для меня спрашивать, почему вы выбираете std:: async даже для простого набора функторов?

Потому что он гарантирует безопасность потоков и распространяет исключения по потокам. Можете ли вы сделать это с помощью простого набора функторов?

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

Не обязательно. Если вы не укажете политику запуска, тогда интеллектуальная реализация может решить, следует ли запускать новый поток или возвращать отложенную функцию или возвращать то, что решает позже, когда доступно больше ресурсов.

Теперь верно, что с реализацией GCC, если вы не предоставляете политику запуска, а затем с текущими версиями, она никогда не будет запускаться в новом потоке (там отчет bugzilla для этого), но это свойство этой реализации, а не std::async в целом. Вы не должны путать спецификацию в стандарте с конкретной реализацией. Чтение реализации одной стандартной библиотеки - плохой способ узнать о С++ 11.

Можете ли вы показать пример, который предоставляется для выполнения в async, без блокировки, способом?

Это не должно блокироваться:

auto fut = std::async(std::launch::async, doSomethingThatTakesTenSeconds);
auto result1 = doSomethingThatTakesTwentySeconds();
auto result2 = fut.get();

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

Ответ 3

Я думаю, что ваша проблема заключается в std::future, говорящей, что она блокируется на get. Он блокирует только если результат еще не готов.

Если вы можете договориться, что результат уже готов, это не проблема.

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

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

В качестве примера представьте себе параллельную рекурсивную сортировку слияния. Он разбивает массив на два куска, затем сортирует async на одном фрагменте при сортировке другого фрагмента. После того, как будет выполнена сортировка его половины, исходный поток не сможет прогрессировать, пока вторая задача не будет завершена. Таким образом, он делает .get() и блокирует. Как только обе половины были отсортированы, он может затем слить (теоретически, слияние может выполняться хотя бы частично параллельно).

Эта задача ведет себя как линейная задача для тех, кто взаимодействует с ней снаружи - когда это делается, массив сортируется.

Затем мы можем обернуть это в задачу std::async и иметь отсортированный массив future. Если мы хотим, мы могли бы добавить условную процедуру, чтобы сообщить нам, что future закончен, но это имеет смысл, если у нас есть поток, ожидающий сигналов.

Ответ 4

В reference: http://en.cppreference.com/w/cpp/thread/async

Если установлен флаг асинхронизации (т.е. политика и std:: launch:: async!= 0), то async выполняет функцию f в отдельном потоке выполнения, как если бы порожденный std:: thread (f, args...), за исключением того, что , если функция f возвращает значение или генерирует исключение, оно сохраняется в общем доступный через std:: future, который async возвращается к Вызывающий.

Это приятное свойство для записи записей об исключениях.