gpt4 book ai didi

clock_gettime(CLOCK_MONOTONIC) 跨核心/线程的单调性

转载 作者:IT王子 更新时间:2023-10-29 01:25:34 27 4
gpt4 key购买 nike

我有多个进程在双处理器 X86-64 Linux 机器的不同内核上相互通信。通信内容包括时间戳。我想在所有时间戳都来自同一个全局时钟的简单假设下编写程序的时间相关逻辑。我能否指望 clock_gettime(CLOCK_MONOTONIC) 为我提供单调时间戳,甚至跨不同内核上运行的不同线程?

特别地,假设进程 A 获取时间戳 X 并通过共享内存将其发送给进程 B。进程B读取它,然后取一个时间戳Y。X不能大于Y。

使用clock_gettime(CLOCK_MONOTONIC) 获取的时间戳是否具有上述属性?如果不是,还有哪些其他类型的单调时间戳具有此属性?

最佳答案

Can I count on clock_gettime(CLOCK_MONOTONIC) to give me monotonic timestamps even across different threads running on different cores?

时间戳仅在同一核心上保证单调。也就是说,如果你有

Thread on CPU A core C                 Thread on CPU B core D

pthread_mutex_lock(&lock);
T1 = clock_gettime(CLOCK_MONOTONIC);
pthread_mutex_unlock(&lock); pthread_mutex_lock(&lock);
T2 = clock_gettime(CLOCK_MONOTONIC);
pthread_mutex_unlock(&lock);

没有绝对保证 T2 > T1


Linux 内核尽最大努力确保 T2 > T1,但问题出在硬件上:某些硬件只是没有足够同步的时间源。在这样的硬件上,创建一个在所有 CPU 和内核之间保持同步的可靠单调时钟将需要进程间中断或其他一些方法来将单个时钟值保存在某处,而这太慢了,效率不高。

在某些配置中,已知时钟源在所有 CPU 内核之间同步。例如,如果所有 physical ID: 字段在 /proc/cpuinfo 中都相同,并且所有 flags: 字段都有 tsc_reliable,则已知时间戳计数器寄存器在所有内核之间同步,并用作时间源。然而,在实践中,您不会进行此类检查,因为结果是推断,内核无法保证,因此可能是错误的。

在实践中,我们计算事物时就好像我们假设 CLOCK_MONOTONIC 是跨内核单调的,但是是务实的和检查的。

对于可能不同内核上的线程之间的定时消息传递或信号,我们测量往返时间。使用大量的往返,并选择时间的中位数:这会给你一个可靠的结果,你可以说“至少有一半的往返在时间 T 内完成" 自信而毫不含糊。 (通常您可能会选择更高的点,例如 68.3% 或 95%。)


如果您需要跨进程访问同一共享内存段的可靠 CLOCK_MONOTONIC 派生时间戳,您可以通过将“当前”时间戳存储在该共享内存中来实现它。

每当进程需要时间戳时,它就相当于

Do:
T0 = clock_gettime(CLOCK_MONOTONIC)
Ts = shared timestamp
T = max(T0, Ts)
While CompareExchange(shared timestamp, Ts, T) fails.
Use T as timestamp.

也就是说,它将本地单调时钟和共享时间戳进行比较,将共享时间戳更新为两者中较高的一个,并将其也用作时间戳。

您可以使用 GCC 的 __atomic_compare_exchange_n()内置更新共享时间戳,无需持有任何锁。 (没有必要从共享内存中原子地读取时间戳,因为原子比较和交换处理原子性。)

唯一的缺点是,如果许多线程经常这样做,您确实会因为缓存行乒乓而获得一些开销。

请注意,如果您使用 uint64_t(以纳秒为单位)作为时间戳,您将需要在 max 函数中考虑回绕:

static inline uint64_t  max_wraparound(const uint64_t  a, const uint64_t  b)
{
return ((uint64_t)(a - b) < UINT64_C(9223372036854775808)) ? a : b;
}

这样,任何两个这样的时间戳,beforeafter 之间的差异总是(uint64_t)(after - before),即使时间戳值介于两者之间。

关于clock_gettime(CLOCK_MONOTONIC) 跨核心/线程的单调性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46893072/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com