【问题标题】:Calling cpuid before rdtsc to prevent out of order? [duplicate]在 rdtsc 之前调用 cpuid 以防止出现故障? [复制]
【发布时间】:2021-11-20 03:28:31
【问题描述】:

我试图在我的 rdtsc 函数之前调用 cpuid 以防止出现故障。我最初使用这个 rdtsc 函数来获取 2 个时间戳,并且经常得到负数,这是不可取的。这是rdtsc函数,我应该如何实现cpuid?还是叫 int main 函数?

inline uint64_t rdtsc() {
    unsigned long a, d;
    asm volatile ("rdtsc":"=a" (a), "=d" (d));
    return a | ((uint16_t)d << 32);
}

【问题讨论】:

  • this question 中的一些信息。还有许多其他人处理这个问题。
  • 通常您希望lfence 作为 OoO exec 的障碍,而不是慢速 CPUID。另请参阅 How to get the CPU cycle count in x86_64 from C++? 以了解运行 rdtsc 的工作代码,它避免将高 32 位截断为 16 位。
  • 另见What's up with the "half fence" behavior of rdtscp?(以及页面顶部链接的重复项列表。其中一些显示_mm_lfence(),或将lfence; rdtsc 放入一个asm 模板中。)
  • 非常感谢。与使用 cpuid 相比,我们能否将 lfence/mfence 描述为一种更集中的序列化指令方式?我注意到使用 cpuid 速度较慢,测量需要更长的时间。

标签: c x86-64 cpuid rdtsc


【解决方案1】:

(uint16_t) d &lt;&lt; 32 的行为未由 C 标准定义。

&lt;&lt; 的左操作数是(uint16_t) d。转换后,将执行整数提升,因此uint16_t 值被转换为int1这在您的 C 实现中可能是 32 位。当移位量等于或超过左操作数宽度时,C 标准没有定义&lt;&lt; 的行为。

要修复此代码,请使用return a | (uint64_t) d &lt;&lt; 32;

大多数编译器都会对此发出警告。注意编译器警告消息。最好将它们提升为错误。 (对于 GCC 或 Clang,使用 -Werror。对于 MSVC,使用 /WX。)

脚注

1 这假设int 的宽度超过 16 位。如果 int 只有 16 位,(uint16_t) d &lt;&lt; 32 仍然未定义,因为 32 比左操作数类型 16 宽。

【讨论】:

    猜你喜欢
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 2018-10-16
    • 2016-07-19
    相关资源
    最近更新 更多