修改C++11原子布尔变量需要多少个时钟周期?

3

我想知道修改std::atomic (或atomic_flag)需要多少个时钟周期,假设它使用最严格的内存模型设置?


10
您缺少许多关键信息:处理器(架构、型号、类型),在您修改数据时该数据位于何处(缓存、主存储器、另一个处理器的缓存),系统中有多少其他处理器,以及其中有多少处理器持有原子变量的副本? - Mats Petersson
1
假设我们有Linux Ubuntu 12.04,2.5 GHz和Intel 64位架构。我关心的场景是该值已经在L1缓存中。然后有两种情况:1)没有其他线程运行,2)多个线程访问变量,但为简单起见,我们假设只有一个生产者和消费者(绑定在不同的核心上)。 - Nathan Doromal
1
几十到几千之间……这不是一个足够好的答案吗? - Mats Petersson
1
这有点愚蠢的问题,答案是:取决于以下因素:a)实现是否无锁 b)是否存在拥塞 c)是否存在数据依赖性——在无锁实现且不存在拥塞和数据依赖性的情况下,它的运行速度取决于CPU可以启动新整数指令的速度(通常为每个时钟周期2-4次)。有了数据依赖性,大约需要20个周期(或者在NUMA系统上不同核心上3-5倍以上)。否则,在拥塞或锁定的情况下,需要……任意数量的周期。 - Damon
1
我刚刚做了一些计时,修改我的设置中的原子布尔值的中位时间为35纳秒。这比修改简单变量要长得多。 - Nathan Doromal
显示剩余2条评论
2个回答

5
确定一次原子操作需要多少个时钟周期是相当困难的。我将尝试解释在假设使用x86处理器(如评论中所述)和运行库使用"locked"指令实现 "atomic"时会发生什么,如果这些假设有任何错误,则像俗话说的那样 "一切皆可能"。
在执行原子操作时,CPU首先将确保对(可能被缓存的)值进行“独占式”访问。这意味着向所有其他CPU发送消息,表示 "我是此变量的主人"。然后,每个其他CPU都必须刷新其副本(如果已修改),并将该值标记为“无效”,然后回复 "我完成了"。
一旦所有处理器都回复了 "我完成了",主处理器就可以继续执行。这个过程在一个具有许多CPU(核心)的大型系统中可能需要相当长的时间(数百或数千周期)。
当然,CPU可以通过知道没有其他CPU读取此值或没有其他CPU发出写入该值的请求来优化此过程,这种情况下可以非常快速。
您可以通过编写一些代码,在两个线程中循环约1秒钟,尝试更新和读取相同的原子变量,并查看它的好坏程度。然后尝试两个 "update" 循环(因此在两个线程之间进行更新)。

1

这大致相当于访问未缓存的主内存。时间在100-1000纳秒左右,或约100个时钟周期。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接