是否可以鼓励线程排队而不强迫它?
Posted
技术标签:
【中文标题】是否可以鼓励线程排队而不强迫它?【英文标题】:is it possible to encourage threads to line up without forcing it? 【发布时间】:2020-10-03 17:06:10 【问题描述】:我有多个线程正在加载的单个原子变量,它们对其执行一些本地计算,然后在其上调用原子的 fetch_and。他们检查他们是否能够在另一个线程之前进行更改,如果没有,则重复使用从 fetch_and 返回的更新值
运行速度比锁定版本快得多。但是,如果我可以鼓励多个线程对齐并且在 fetch_and 完成而不强制它完成之前不加载原子序数,那就太好了。
这可能吗?认为它可能正在使用一两个内存栅栏?
【问题讨论】:
这如何比单线程版本运行得更快,因为您似乎在说所有正在运行的线程中只有 1 个线程可以更新共享原子? 进入细节,我正在对原子进行按位操作,然后检查是否成功。不同的线程通常会旋转不同的位,并且只检查没有其他线程接触过一个特定的位。所以大多数时候他们能够各自做自己的事情,只是偶尔会踩到对方的脚。虽然锁很便宜,但锁争用不是,而且单个原子更快,实际上我通常可以跳过初始加载,只 fetch_and。这是我的猜测。在基准测试中运行速度比使用锁定快 10 倍左右。 他们检查他们是否能够在另一个线程之前进行更改 - 让线程使用 CAS 来应用更改是否有用?即使用 CAS 构建自定义原子 RMW。还是 AND 操作仍然有用? (另请注意,x86 没有硬件 fetch_and,只有原子and
不返回旧值,如果这很重要,因此使用 fetch_and 的返回值强制编译器在内部使用 CAS 重试循环来模拟它)。如果您有线程争用,手动 CAS 不能解决浪费工作的问题,因此可能没有帮助。
顺便说一句,内存屏障仅命令 this 内核访问一致性缓存。如果您知道要查找的内容,则可以只读方式旋转,直到看到一个使“成功”成为可能的值,无论这意味着什么。仍然不清楚到底重复了什么(计算或只是另一个原子 fetch_and);一个例子会有所帮助。
如果原子版本在您的特定测试中比锁定版本执行得更好,那么这并不意味着在其他一些测试中它不是直接相反的或者第三个(例如异步排队)版本不能对于并发的实际使用,甚至比任何一个都好(因为测试通常会遗漏某些方面)。
【参考方案1】:
没有意义。如果两个线程不尝试同时执行此操作,它们将取得完美的进展。如果两个线程确实尝试同时执行此操作,则其中一个线程将不得不以某种方式等待。其他线程等待的方式对性能没有影响。
如果每个线程在访问原子变量之间需要大约相同的时间,它们会自然地排成一行,因为它们会一次通过第一次这样的访问。如果线程需要不同的时间,那么排列它们的任何尝试都不可能成功。防止两个线程同时到达的唯一方法是减慢其中一个线程的速度,而它们同时到达的后果就是其中一个线程变慢了。
如果本地计算花费的时间太长,以至于您的代码可能会花费大量时间进行被丢弃的计算,请改用锁。
【讨论】:
以上是关于是否可以鼓励线程排队而不强迫它?的主要内容,如果未能解决你的问题,请参考以下文章