struct _Mtx_internal_imp_t
{ /* Win32 mutex */
int type; // here MS keeps particular mutex type
Concurrency::critical_section cs;
long thread_id;
int count;
};
#include <mutex>
enum class __stl_sync_api_modes_enum { normal, win7, vista, concrt };
extern "C" _CRTIMP2 void __cdecl __set_stl_sync_api_mode(__stl_sync_api_modes_enum mode);
int main()
{
__set_stl_sync_api_mode(__stl_sync_api_modes_enum::vista);
std::mutex protect; // now it is forced to use CRITICAL_SECTION inside
}
6条答案
按热度按时间ekqde3dh1#
请看我在答案末尾的更新,自Visual Studio 2015以来,情况发生了巨大变化。原始答案如下。
我做了一个非常简单的测试,根据我的测量,
std::mutex
比CRITICAL_SECTION
慢50- 70倍左右。编辑:经过更多的测试,它原来取决于线程数(拥塞)和CPU核心数。一般来说,
std::mutex
是慢,但多少,这取决于使用。以下是更新的测试结果(测试的MacBook Pro与核心i5- 4258 U,Windows 10,Bootcamp):以下是生成此输出的代码。使用Visual Studio 2012、默认项目设置和Win32版本配置编译。请注意,此测试可能不完全正确,但它使我在将代码从
CRITICAL_SECTION
切换到std::mutex
之前三思而后行。std::mutex
的“开销”,它并不是试图证明99%的应用程序的差异是可以忽略的。std::mutex
有利。我使用了VS 2017 IDE,与上面完全相同的代码,x64发布配置,禁用优化,我只是简单地切换了每个测试的“平台工具集”。结果非常令人惊讶,我真的很好奇VC 140中挂起了什么。std::mutex
比CRITICAL_SECTION
快两到三倍。juud5qan2#
waldez的测试是不现实的,它基本上模拟了100%的竞争。一般来说,这正是你不希望在多线程代码。下面是一个修改后的测试,它做了一些共享计算。我用这个代码得到的结果是不同的:
这里你可以看到,对于我(使用VS2013)来说,std::mutex和CRITICAL_SECTION之间的数字非常接近。注意,这段代码执行固定数量的任务(160,000),这就是为什么性能随着线程数量的增加而提高。我这里有12个内核,所以我在12个内核上停了下来。
我并不是说与其他测试相比,这是正确的还是错误的,但它确实强调了时序问题通常是特定于领域的。
3lxsmp7m3#
我在这里搜索pthread与临界区的基准测试,然而,我的结果与waldez关于这个主题的回答不同,我想分享一下会很有趣。
代码是@waldez使用的,修改后添加了pthreads到比较中,用GCC编译,没有优化。我的CPU是AMD A8- 3530 MX。
Windows 7家庭版:
正如您所看到的,差异在统计误差范围内变化很大-有时std::mutex更快,有时不是。重要的是,我没有观察到像原始答案那样大的差异。
我想,也许原因是,当答案被张贴,MSVC编译器是不好与较新的标准,并注意到,原来的答案已使用的版本从2012年.
另外,出于好奇,在Archlinux上的Wine下也有同样的二进制文件:
Waldez的密码加上我的修改
uoifb46i4#
2015年2月的原始答复:
我使用的是Visual Studio 2013。
我在单线程使用方面的结果看起来与waldez的结果相似:
100万次锁定/解锁调用:
Microsoft更改实现的原因是C11兼容性。C11在标准名称空间中有4种互斥锁:
Microsoft std::mutex和所有其他mutex是关键部分周围的 Package 器:
对于我来说,std::recursive_mutex应该完全匹配临界区。所以微软应该优化它的实现,以占用更少的CPU和内存。
2023年2月更新:
最新调查显示,最新版本的MSVC与MSVC 2013相比,
std::mutex
实现存在差异。我尝试了以下编译器/STL,它们显示了相同的行为:默认情况下,它们都使用SRW locks实现
std::mutex
。但是CRT在运行时仍然可以选择基于CRITICAL_SECTION的实现。
下面是现代底层结构的定义:
它是这样初始化的:
are_win7_sync_apis_available
正在检查运行时是否存在API函数TryAcquireSRWLockExclusive
。如您所见,例如,如果
create_stl_critical_section
运行在Windows Vista上,它将选择stl_critical_section_vista
。我们还可以通过调用未记录的函数
__set_stl_sync_api_mode
来强制CRT选择基于CRITICAL_SECTION的实现:这对动态CRT链接(DLL)和静态CRT都有效。但是静态CRT的调试要容易得多(在调试模式下)。
tzcvj98z5#
Waldez修改了相同的test program,以使用pthreads和boost::mutex运行。
在win10 pro上(使用intel i7- 7820 X 16核cpu),我从VS2015 update 3上的std::mutex得到了比CRITICAL_SECTION更好的结果(从boost::mutex得到的结果甚至更好):
pthreads的结果为here。
sulc1iza6#
对于测试2