19

x86 和其他架构提供了特殊的原子指令(lock、cmpxchg 等),允许您编写“无锁”数据结构。但是随着越来越多的内核被添加,这些指令实际上必须在幕后完成的工作似乎会增加(至少要保持缓存一致性?)。如果今天在双核系统上原子添加需要大约 100 个周期,那么在未来的 80 多核机器上可能需要更长的时间吗?如果您要编写持久的代码,那么使用锁实际上可能是一个更好的主意,即使它们今天速度较慢?

4

4 回答 4

15

你是对的,一旦计数开始超过几十个,拓扑约束将以一种或另一种方式增加核心之间的通信延迟。我真的不知道 x86 公司处理这种扩展的意图是什么。

但是锁是根据原子操作来实现的。因此,尝试切换到它们并不能真正赢得胜利,除非它们以比您自己的手动原子操作尝试的更具可扩展性的方式实现。我认为,一般来说,对于类似单个令牌的争用,无论您拥有多少个核心,原子原语仍然是最快的方式。

正如克雷很久以前发现的那样,这里没有免费的午餐。在高级软件设计中,您尝试尽可能少地使用可能存在争议的资源,这将始终为大规模并行化应用程序带来最大的回报。这意味着尽可能多地完成锁定获取的结果,但也要尽可能快。在极端情况下,这可能意味着在假设成功获取锁的情况下预先计算您的工作,尝试抓住它,并在成功时尽快完成,否则丢弃您的工作并重试失败。

于 2009-10-18T20:48:14.263 回答
7

对于标题中提出的问题,简短的回答是“是”,长的回答是“很复杂”。

关于锁更好,不。在内部,锁必须至少通过总线推动尽可能多(如果不是更多)的流量。这样想,如果处理器只有一个原子操作,一个原子比较和交换,你可以用它来实现锁和原子增量。好吧,在总线协议级别,只使用了几个原语。锁并不比原子操作慢,因为它们正在做不同的事情,它们更慢是因为它们做更多相同的事情(从一致性的角度来看)。因此,随着原子操作速度变慢,锁也会相应变慢。

话虽如此,关于这个主题的论文很多,具体案例也很复杂。我不会担心您的代码将如何在具有不可预测的性能特征的 80 个核心 CPU 上扩展(因为我们不知道它们将如何设计)。要么它们的行为像我们当前的 CPU 一样,你的代码会正常运行,要么它们不会,你现在猜到的任何东西都会被证明是错误的。在大多数情况下,代码无论如何都不是性能敏感的,所以没关系,但如果确实如此,那么当您了解架构和性能特征时,适当的做法是在将来修复它您的目标处理器。

于 2009-10-18T20:13:48.997 回答
3

我不认为问题在于原子操作本身会花费更长的时间。真正的问题可能是原子操作可能会阻塞其他处理器上的总线操作(即使它们执行非原子操作)。

如果您想编写持久的代码,请尽量避免首先锁定。

于 2009-10-18T20:23:43.260 回答
1

在这个问题的旁注中,值得一提的是,您所指的未来已经是 GPU 中的现有技术。现代的 quadro GPU 有多达 256 个内核,可以在全局(显示)内存上执行原子操作。
我不确定这是如何实现的,但事实是它已经在发生。

于 2009-10-18T22:49:20.790 回答