2

http://blog.memsql.com/common-pitfalls-in-writing-lock-free-algorithms/的末尾,David Stolp 显示了无锁堆栈的性能数据,表明无锁版本比受保护的顺序版本慢通过互斥体,即使争用增加。结果很有趣,但有两件事让我担心:

  • 充其量,“整体吞吐量”会随着线程数量的增加而降低,然后趋于平稳。总吞吐量不应该随着线程数量的增加而增加吗?
  • 在最终图表中,1 个线程的性能值范围约为 35M 到 55M。对于 1 个线程来说,这似乎是一个非常广泛的范围(不能有任何争用)。

我试图找到一种方法就这些问题联系作者,但没有成功,所以我转向 SO 社区,看看结果是否现实。他们有吗?

4

2 回答 2

1

充其量,“整体吞吐量”会随着线程数量的增加而降低,然后趋于平稳。总吞吐量不应该随着线程数量的增加而增加吗?

这很正常!堆栈只有一个!瓶颈是线程之间的内存同步,而不是代码执行。因此,如果更多线程填充堆栈,则应该发生更多内存冲突(出现竞争条件),因此吞吐量会降低。

在最终图表中,1 个线程的性能值范围约为 35M 到 55M。对于 1 个线程来说,这似乎是一个非常广泛的范围(不能有任何争用)。

这个测试代码是不现实的,因为它只是将节点弹出并推入堆栈。因此,相对较短的代码的最小差异会极大地影响吞吐量。

如果您检查代码,您会发现 SpinLock 版本非常简单并且可能比 LockFree 更快,因为它是使用test_and_set原子函数制成的,通常比CASLockFree 版本中使用的原子(比较和交换)更快。

编辑:

在 LockFree 版本中使用cmpxchg16b的是 16 字节的 CAS 在 SpinLock 中仅使用了 8 字节的 test_and_set 函数(用 实现cmpxchg8b),因此存在速度差异!

于 2013-10-03T23:05:26.680 回答
1

充其量,“整体吞吐量”会随着线程数量的增加而降低,然后趋于平稳。总吞吐量不应该随着线程数量的增加而增加吗?

不一定,在这种情况下绝对不是。如果执行线程可以同时运行,多线程是有益的。如果线程永远不能同时运行,或者如果几乎所有执行都涉及对单个资源的争用,则最好使应用程序成为单线程。

此测试旨在使线程不能同时运行。几乎所有的代码都在争夺一个资源,一个堆栈。在这里故意使用这种名义上糟糕的设计,以便测试各种并发执行方案的开销,并测试各种方案处理争用的能力。

在最终图表中,1 个线程的性能值范围约为 35M 到 55M。对于 1 个线程来说,这似乎是一个非常广泛的范围(不能有任何争用)。

即使没有争用,锁定和解锁互斥体也会产生大量开销。比较和交换的开销要少得多,测试和设置的开销更少。当只有一个执行线程时,这种纯粹的开销是正在测试的。

于 2013-10-04T07:29:57.793 回答