__rdtscp校准在Intel Xeon X5550的Linux下不稳定

感觉

我正在尝试使用__rdtscp内在函数来测量时间间隔。目标平台是Linux x64,CPU英特尔至强X5550。尽管constant_tsc为此处理器设置了标志,但校准__rdtscp会产生非常不同的结果:

$ taskset -c 1 ./ticks
Ticks per usec: 256
$ taskset -c 1 ./ticks
Ticks per usec: 330.667
$ taskset -c 1 ./ticks
Ticks per usec: 345.043
$ taskset -c 1 ./ticks
Ticks per usec: 166.054
$ taskset -c 1 ./ticks
Ticks per usec: 256
$ taskset -c 1 ./ticks
Ticks per usec: 345.043
$ taskset -c 1 ./ticks
Ticks per usec: 256
$ taskset -c 1 ./ticks
Ticks per usec: 330.667
$ taskset -c 1 ./ticks
Ticks per usec: 256
$ taskset -c 1 ./ticks
Ticks per usec: 330.667
$ taskset -c 1 ./ticks
Ticks per usec: 330.667
$ taskset -c 1 ./ticks
Ticks per usec: 345.043
$ taskset -c 1 ./ticks
Ticks per usec: 256
$ taskset -c 1 ./ticks
Ticks per usec: 125.388
$ taskset -c 1 ./ticks
Ticks per usec: 360.727
$ taskset -c 1 ./ticks
Ticks per usec: 345.043

如我们所见,程序执行之间的差异最多可以达到3倍(125-360)。这种不稳定性不适用于任何测量。

以下是代码(gcc 4.9.3,在Oracle Linux 6.6上运行,内核3.8.13-55.1.2.el6uek.x86_64):

// g++ -O3 -std=c++11 -Wall ticks.cpp -o ticks
#include <x86intrin.h>
#include <ctime>
#include <cstdint>
#include <iostream>

int main()
{       
    timespec start, end;
    uint64_t s = 0;

    const double rdtsc_ticks_per_usec = [&]()
    {
        unsigned int dummy;

        clock_gettime(CLOCK_MONOTONIC, &start);

        uint64_t rd_start = __rdtscp(&dummy);
        for (size_t i = 0; i < 1000000; ++i) ++s;
        uint64_t rd_end = __rdtscp(&dummy);

        clock_gettime(CLOCK_MONOTONIC, &end);

        double usec_dur = double(end.tv_sec) * 1E6 + end.tv_nsec / 1E3;
        usec_dur -= double(start.tv_sec) * 1E6 + start.tv_nsec / 1E3;

        return (double)(rd_end - rd_start) / usec_dur;
    }();

    std::cout << s << std::endl;
    std::cout << "Ticks per usec: " << rdtsc_ticks_per_usec << std::endl;
    return 0;
}

当我在Windows 7,i7-4470,VS2015下运行非常相似的程序时,校准结果非常稳定,只有最后一位的差异很小。

那么问题来了-那是什么问题呢?是CPU问题,Linux问题还是我的代码问题?

感觉

绝对是我的代码(或gcc)问题。编译器优化了循环,将其替换为s = 1000000

为防止gcc优化此校准回路,应按以下方式进行更改:

for (size_t i = 0; i < 1000000; ++i) s += i;

或更简单正确的方法(感谢Hal):

for (volatile size_t i = 0; i < 1000000; ++i);

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

需要Linux Mint 18的Intel Xeon E3-1200驱动程序

为Intel Xeon Gold 6148构建TensorFlow

Ubuntu 14.04与Intel wifi卡的不稳定wifi连接

使用Intel Python 2019和Xeon Phi(KNC)自动卸载

Intel Xeon Platinum 8168 CPU上的Vmovntpd指令

14.04LTS上的Intel Xeon Phi 7120p

将功能转移到Intel Xeon Phi所需的时间

当Debian中的游标不稳定时,如何校准插入光标的位置?

集成Intel 5500图形和Debian上的硬件加速导致系统不稳定

可以将Python 3.6与Intel MKL 2017和Xeon Phi KNC卡一起使用

这个 Intel Xeon mov 指令是如何破坏我的应用程序内存的?

Intel i7和Xeon四核处理器之间有什么区别?

无法在Intel Xeon Phi上执行二进制错误

为什么相同的OpenCL代码从Intel Xeon CPU和NVIDIA GTX 1080 Ti GPU输出不同?

从Intel E2160升级到Xeon 3220后,桌面无法发布

Intel Xeon E5-2630 v4工作站中的Ubuntu 16.04 LTS?

在Ubuntu而非Windows下不稳定的视频

Ubuntu18.04而非Windows下不稳定的视频

virtualbox中没有64位虚拟化(Intel S1200RP主板+ Xeon 1270 v3)

2个Xeon X5650 CPU,但每个CPU仅6个线程

对int不稳定?

数值不稳定?

为通用x86 / 64和Xeon或其他版本编译的Linux内核之间有什么区别

Mathnet Numerics with Intel MKL 在 Intel Xeon Gold 上的运行速度比旧的 i7-7700HQ 笔记本电脑慢得多

从Intel Xeon Phi上的AVX512到Intel i5-8259U上的AVX2,将会失去什么?

Python 响应模块在 Linux 中的多线程不稳定

Java的禁止警告“X标记不稳定”

如何在Linux中的Ivy Bridge Xeon E3处理器上监视RAM ECC错误?

ECS服务不稳定