Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 原子/联锁变量与锁相比有多快,有无争用?_C++_Multithreading_Performance_X86 64_Thread Synchronization - Fatal编程技术网

C++ 原子/联锁变量与锁相比有多快,有无争用?

C++ 原子/联锁变量与锁相比有多快,有无争用?,c++,multithreading,performance,x86-64,thread-synchronization,C++,Multithreading,Performance,X86 64,Thread Synchronization,与无冲突的原子变量(例如C++的std::atomic)操作相比,它的速度要快/慢多少 另外,有争议的原子变量相对于无争议的锁要慢多少 我正在研究的体系结构是x86-64。取决于锁的实现,也取决于系统。原子变量不能像锁一样受到质疑(即使您正在使用),这是原子性的全部要点,它锁定总线以传播存储(取决于内存屏障模式),但这是一个实现细节 然而,大多数用户模式锁都是包装好的原子操作,有关在x86和x64下使用原子操作的高性能、可扩展锁的一些数据,请参阅Intel的文章(与Windows的Critica

与无冲突的原子变量(例如C++的
std::atomic
)操作相比,它的速度要快/慢多少

另外,有争议的原子变量相对于无争议的锁要慢多少


我正在研究的体系结构是x86-64。

取决于锁的实现,也取决于系统。原子变量不能像锁一样受到质疑(即使您正在使用),这是原子性的全部要点,它锁定总线以传播存储(取决于内存屏障模式),但这是一个实现细节


然而,大多数用户模式锁都是包装好的原子操作,有关在x86和x64下使用原子操作的高性能、可扩展锁的一些数据,请参阅Intel的文章(与Windows的CriticalSection锁相比,不幸的是,找不到锁的统计信息,但应始终针对自己的系统/环境进行配置).

我碰巧有很多低级别的速度测试。但是,速度的确切含义非常不确定,因为它在很大程度上取决于你到底在做什么(甚至与操作本身无关)

以下是AMD 64位Phenom II X6 3.2Ghz的一些数字。我也在Intel芯片上运行过,时间确实有很大的不同(同样,这取决于正在做的事情)

GCC
\uuuuuuu sync\u fetch\u和uu add
,这将是一个完全隔离的原子加法,平均值为16ns,最小时间为4ns。最小时间可能更接近事实(即使在那里我也有一点开销)

未竞争的pthread互斥体(通过boost)为14ns(这也是它的最小值)。请注意,这也有点太低,因为如果有其他东西锁定了互斥体,时间实际上会增加,但现在它不是无竞争的(因为它会导致缓存同步)

失败的try_锁为9ns

我没有一个普通的原子inc,因为在x86_64上,这只是一个正常的交换操作。可能接近最短时间,所以1-2ns

在条件变量上没有服务员的情况下调用notify是25ns(如果有东西在等待304ns)

但是,由于所有锁都会导致某些CPU排序保证,因此修改的内存量(存储缓冲区中适合的内存量)将改变此类操作所需的时间。显然,如果您在互斥上发生争用,这是您最糟糕的时间。即使没有实际发生线程切换,任何返回linux内核的时间都可能长达数百纳秒。这通常是原子锁执行的地方,因为它们从不涉及任何内核调用:您的平均情况性能如果存在等待线程,互斥解锁也会产生开销,而原子线程则不会


注意:进行这样的测量充满了问题,因此结果总是有点可疑。我的测试试图通过固定CPU速度、设置CPU与线程的相关性、不运行其他进程以及在大型结果集上求平均值来最小化变化。

有一种方法可以在不同的平台上进行测量。不值得一提的是,在我的硕士论文之后,我从来没有真正的时间来跟进这一点,但至少基本的代码在那里

它测量pthreads和OpenMP锁,与
\uuu sync\u fetch\u和\u add
固有值相比

据我记忆所及,我们曾预期锁和原子操作之间会有相当大的差异(~一个数量级),但实际差异却非常小


但是,现在在我的系统上进行测量会得到反映我最初猜测的结果,即(无论使用pthreads还是OpenMP)原子操作的速度大约是原来的五倍,单个锁定增量操作大约需要35ns(这包括获取锁、执行增量和释放锁)

“原子变量不能像锁一样被竞争”--如果两个线程(在不同的核心上)锤击同一个原子变量,那么这就是对它的挑战,当然?这取决于体系结构/实现,是否存在竞争实际上会减慢速度。您可以将其与不同内核上的两个线程锤击同一个非原子变量进行比较,以了解原子同步在某种意义上是否需要任何时候都可以进行同步。@SteveJessop,当然可以。使用同一变量的两个内核将导致该变量的过度同步。此时,缓存总线的延迟/带宽限制了您。@SteveJessop:您可以这样称呼它,但是,在我看来,它是以不同的方式一起完成的,因此您不能真正将其与spin wait ret归入同一类别“正在尝试一个已经获得的锁。@edA-qamort-ora-y:这个问题在类似x86的体系结构上可能会被混淆,因为有一致的缓存。所以就像你说的,敲打同一个位置是一种争论,即使它不是一个原子变量。我不确定提问者是否知道这一点,但如果你找出有争议的原子增量的“成本”是多少。您可以将其与单个线程中的原子增量进行比较,或者与有争议的非原子增量(也称为数据竞赛)进行比较,并对什么是“原子争用”提出非常不同的想法“成本”。@Necrolis:当然,机制完全不同,但我认为提问者将所有这些事情称为“争用”是正确的。如果我的代码被延迟,等待其他代码离开,那么无论是什么机制,我们都在争用:-)@KonradRudolph,我看到问题是相似的,但并不完全相同。这一个更关注操作的基本成本,而另一个是算法的两种方法的间接成本。实际上,我的回答会有所不同。@edA-qamort-ora-y是另一个问题的作者