Поведение GCC с std::async(std::launch::async) и поведение Clang
Есть ли у кого-нибудь опыт работы с относительно новыми std::async
? В настоящее время мы реализуем параллельный анализатор файлов, который считывает кусок файла и передает этот блок асинхронной функции.
Используя Clang (v3.0), этот способ действительно отлично работает по умолчанию std::async
политика (зависит от реализации). На двухъядерной машине он запускает до 4 потоков, что действительно хорошо работает.
Но с GCC (v4.7) поток чтения файлов не создает никаких новых потоков, что делает программу в конце полностью последовательной.
С помощью std::launch::async
обе версии в значительной степени делают одно и то же (что должно быть).
Кто-нибудь знает состояние текущих возможностей потоков GCC C++11? Или это может быть ошибкой в нашей реализации?
Короткий номер:
while (readNewChunk()) {
Chunk &chunk = fileReader_.getChunk(); //reading the file
ChunkLoader *chunkLoader = new ChunkLoader();
auto ftr = std::async(std::launch::async, &ChunkLoader::createDictionaries, chunkLoader);
dictCreationFutures_.push_back(std::move(ftr));
}
4 ответа
Поведение находится в пределах спецификации, даже если это не то, что вы хотите. Если вы не укажете политику запуска, она считается async|deferred
, что означает, что это зависит от реализации, чтобы решить, какой. GCC всегда выбирает deferred
если есть выбор.
EDIT2: я объясню немного больше.
std:: async обещает "будущее"; то есть: когда ты этого захочешь, он будет там. Это может быть вычислено сейчас, это может быть вычислено, когда вы просите об этом, мы просто обещаем, что это произойдет.
Как и в приведенном ниже сообщении, отмеченном мной, GCC по умолчанию имеет значение deferred (что означает, что он выполнит это обещание, когда его об этом попросят, и, вероятно, не заранее). Причина по умолчанию заключается в том, что GCC пока не обеспечивает надлежащей поддержки потоков C++11. Он не имеет хорошего внутреннего планировщика потоков, среди многих других вещей. Это немного взломать. Нет, больше похоже на кучу хаков. На самом деле, если вы пишете многопоточный код на C++11 на GCC, тем более, что когда они действительно реализуют функции, все будет работать правильно; сейчас это в основном работает правильно. Я имею в виду, вы получите результат в конце концов, верно?
Если вы скажете ему запустить поток, это произойдет, потому что он слишком глуп (на данный момент), чтобы понять, что он может и должен сам по себе (в отличие от CLang, который в настоящее время имеет лучший внутренний планировщик потоков).
РЕДАКТИРОВАТЬ: серьезно? Дезинформированный down-моддинг!
Вот моя ссылка! http://gcc.gnu.org/projects/cxx0x.html. Обратите внимание, что почти все в "параллелизме", включая "модель памяти", помечено как НЕТ. GCC.GNU.org. Вы знаете, это авторитет в GCC.
Слегка отредактировано из моего комментария:
Я бы очень рекомендовал использовать Boost. Это не будет большим переходом к правильной поддержке C++11, когда GCC будет готов. Новые модели многопоточности в C++11 требуют другого макета памяти, чем GCC или MSVC, и они пока еще не реализованы.
Обновленный ответ: будут выполнены GCC 7.3.0 и Clang 6.0. std::async()
работать на отдельных потоках для политики запуска по умолчанию. Оба создадут столько потоков, сколько std::async()
звонки (проверено 100 звонками).
Я не знаю, когда это поведение изменилось для GCC.
Итак, я понимаю, что это 2 года спустя, но я не могу не почувствовать необходимость ответить на комментарий @std''OrgnlDave о GCC против CLang, отметив, что, по крайней мере, в настоящее время, январь 2015 года, обе версии clang 3.5 и GCC версии 4.9 ведут себя точно так же. Такое поведение, когда политика запуска не указана, по умолчанию отличается и выполняется при вызове future::get, и только когда явно указана политика асинхронного запуска, любой из компиляторов приведет к выполнению функции в фоновом режиме.