C++ std::thread到std::async可以获得巨大的性能增益。怎么可能呢?

C++ std::thread到std::async可以获得巨大的性能增益。怎么可能呢?,c++,multithreading,c++11,stdasync,C++,Multithreading,C++11,Stdasync,我在std::thread和std::async之间编写了一个测试代码 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 名称空间fs=boost::filesystem; 名称空间pt=boost::posix_time; 名称空间as=boost::asio; 类日志:私有boost::不可复制 { 公众: void LogPath(常量fs::path和filePath){ boost::system::error_code ec; 如

我在std::thread和std::async之间编写了一个测试代码

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
名称空间fs=boost::filesystem;
名称空间pt=boost::posix_time;
名称空间as=boost::asio;
类日志:私有boost::不可复制
{
公众:
void LogPath(常量fs::path和filePath){
boost::system::error_code ec;
如果(fs::存在(文件路径,ec)){
fs::remove(文件路径);
}
这->ofStreamPtr_u2;.reset(新的fs::ofstream(文件路径));
};
无效写日志(标准::大小\u t i){
断言(*this->ofStreamPtr_);
std::lock\u guard lock(此->日志互斥锁);

*此->ofStreamPtr\up>函数可能永远不会被调用。在版本2中,您没有传递
std::launch
策略,因此您依赖于(强调我的):

行为与
async(std::launch::async | std::launch::deferred,f,args…)相同。换句话说,
f
可以在另一个线程中执行,也可以在查询结果
std::future
的值时同步运行。

尝试使用以下小更改重新运行基准测试:

auto result = std::async(std::launch::async, func, i);
或者,您可以在第二个循环中对每个
std::future
调用
result.wait()
,类似于对版本1中的所有线程调用
join()
。这将强制对
std::future
进行评估


请注意,此基准测试存在一个重大的、不相关的问题。
func
会在函数调用的整个过程中立即获得一个锁,这使得并行性不可能实现。在这里使用线程没有任何好处-我怀疑它会明显变慢(由于线程创建和锁定开销)而不是串行实现。

该函数可能永远不会被调用。在版本2中,您没有传递
std::launch
策略,因此您依赖于(强调我的):

行为与
async(std::launch::async | std::launch::deferred,f,args…)相同。换句话说,
f
可以在另一个线程中执行,也可以在查询结果
std::future
的值时同步运行。

尝试使用以下小更改重新运行基准测试:

auto result = std::async(std::launch::async, func, i);
或者,您可以在第二个循环中对每个
std::future
调用
result.wait()
,类似于对版本1中的所有线程调用
join()
。这将强制对
std::future
进行评估


请注意,此基准测试存在一个重大的、不相关的问题。
func
会在函数调用的整个过程中立即获得一个锁,这使得并行性不可能实现。在这里使用线程没有任何好处-我怀疑它会明显变慢(由于线程创建和锁定开销)而不是串行实现。

在我看来,您启动的线程太多(超过cpu内核)由于它们都在争夺cpu时间和上下文切换,所以速度很慢。在异步情况下,运行时在足够多的线程上高效地管理和执行代码,并在需要时产生处理器时间。使线程非常庞大。任何超过核心数目的操作都会降低性能(忽略被锁/IO阻止的线程)。这就是建议使用线程池的原因。您的代码在100000次迭代中失败是一个足够大的提示。线程是一个昂贵的操作系统对象,您需要支付创建它们并再次拆除它们的成本。如果线程完成的工作量如此之小,那么您肯定会看到开销。std::async实现在可以分摊成本的情况下,使用线程池是一种标准技术。一个粗略的指导原则是,一个线程应该至少运行100微秒,一个异步函数不应该超过一秒钟。在我看来,你启动的线程太多了(超过cpu核数)由于它们都在争夺cpu时间和上下文切换,所以速度很慢。在异步情况下,运行时在足够多的线程上高效地管理和执行代码,并在需要时产生处理器时间。使线程非常庞大。任何超过核心数目的操作都会降低性能(忽略被锁/IO阻止的线程)。这就是建议使用线程池的原因。您的代码在100000次迭代中失败是一个足够大的提示。线程是一个昂贵的操作系统对象,您需要支付创建它们并再次拆除它们的成本。如果线程完成的工作量如此之小,那么您肯定会看到开销。std::async实现在可以分摊成本的情况下,使用线程池是一种标准技术。一个粗略的指导原则是,线程应至少运行100微秒,异步函数不应超过一秒钟。是的,你说得对。如果不指定启动策略,该代码将永远不会运行……我将代码更改为使用std::launch::async,这样可以提高效率性能与第1版完全相同。(10000次迭代时为0.29s)注意:删除
std::lock_-guard
没有任何性能提升。我建议将并行代码与串行实现进行基准测试,作为一种健全性检查。您绝对不应该删除
std::lock_-guard
,因为
std::fstream
不是线程安全的。此外,如果这回答了您最初的问题,请是的,你是对的。没有指定启动策略,代码永远不会运行……我把代码改为使用STD::Actudi::AsiNC,它与版本1的性能完全相同。(10000个错误的0.29秒)注意:删除
std::lock\u guard
没有任何性能提升,我建议将并行代码与串行实现进行基准测试,作为一种健全性检查。您肯定应该这样做