标签: rdtsc

rdtscp,rdtsc:memory和cpuid/rdtsc之间的区别?

假设我们正在尝试使用tsc进行性能监控,我们希望防止指令重新排序.

这些是我们的选择:

1: rdtscp是序列化调用.它可以防止对rdtscp的调用进行重新排序.

__asm__ __volatile__("rdtscp; "         // serializing read of tsc
                     "shl $32,%%rdx; "  // shift higher 32 bits stored in rdx up
                     "or %%rdx,%%rax"   // and or onto rax
                     : "=a"(tsc)        // output to tsc variable
                     :
                     : "%rcx", "%rdx"); // rcx and rdx are clobbered
Run Code Online (Sandbox Code Playgroud)

但是,rdtscp仅适用于较新的CPU.所以在这种情况下我们必须使用rdtsc.但是rdtsc非序列化,因此单独使用它不会阻止CPU重新排序.

所以我们可以使用这两个选项中的任何一个来防止重新排序:

2:这是一个电话cpuid然后rdtsc.cpuid是一个序列化的电话.

volatile int dont_remove __attribute__((unused)); // volatile to stop optimizing
unsigned tmp;
__cpuid(0, tmp, tmp, tmp, …
Run Code Online (Sandbox Code Playgroud)

c c++ performance assembly rdtsc

61
推荐指数
2
解决办法
3万
查看次数

跨CPU核心的rdtsc精度

我正在从一个线程发送网络数据包,并在另一个运行在不同CPU核心上的线程上接收回复.我的进程测量每个数据包的发送和接收之间的时间(类似于ping).我正在使用rdtsc来获得高分辨率,低开销的时序,这是我的实现所需要的.

所有测量看起来都很可靠.尽管如此,我仍然担心核心的rdtsc准确性,因为我一直在阅读一些暗示tsc未在核心之间同步的文本.

在维基百科上找到了关于TSC的以下信息

恒定的TSC行为可确保每个时钟周期的持续时间均匀,并支持将TSC用作挂钟定时器,即使处理器内核更改频率也是如此.这是所有英特尔处理器的架构行为.

我仍然担心核心的累积性,这是我的问题

更多信息

  • 我在Intel nehalem机器上运行我的进程.
  • 操作系统是Linux.
  • 为所有核设置" constant_tsc "cpu标志.

linux multicore rdtsc

31
推荐指数
1
解决办法
2万
查看次数

英特尔失去了周期?rdtsc和CPU_CLK_UNHALTED.REF_TSC之间的不一致

在最近的CPU上(至少在过去十年左右),除了各种可配置的性能计数器之外,英特尔还提供了三个固定功能硬件性能计数器.三个固定柜台是:

INST_RETIRED.ANY
CPU_CLK_UNHALTED.THREAD
CPU_CLK_UNHALTED.REF_TSC
Run Code Online (Sandbox Code Playgroud)

第一个计算退役指令,第二个计算实际周期,最后一个是我们感兴趣的."英特尔软件开发人员手册"第3卷的描述如下:

当核心未处于暂停状态而不处于TM停止时钟状态时,此事件计算TSC速率下的参考周期数.核心在运行HLT指令或MWAIT指令时进入暂停状态.此事件不受核心频率变化(例如,P状态)的影响,但计数与时间戳计数器的频率相同.当核心未处于暂停状态而不处于TM stopclock状态时,此事件可以估计经过的时间.

因此,对于CPU绑定循环,我希望该值与从中读取的自由运行TSC值相同rdstc,因为它们应该仅针对暂停的循环指令或"TM stopclock state"是什么发散.

我使用以下循环测试它(整个独立演示在github上可用):

for (int i = 0; i < 100; i++) {
    PFC_CNT cnt[7] = {};

    int64_t start = nanos();
    PFCSTART(cnt);
    int64_t tsc =__rdtsc();
    busy_loop(CALIBRATION_LOOPS);
    PFCEND(cnt);
    int64_t tsc_delta   = __rdtsc() - tsc;
    int64_t nanos_delta = nanos() - start;

    printf(CPU_W "d" REF_W ".2f" TSC_W ".2f" MHZ_W ".2f" RAT_W ".6f\n",
            sched_getcpu(),
            1000.0 * cnt[PFC_FIXEDCNT_CPU_CLK_REF_TSC] / nanos_delta,
            1000.0 * tsc_delta / nanos_delta,
            1000.0 * CALIBRATION_LOOPS / nanos_delta,
            1.0 * cnt[PFC_FIXEDCNT_CPU_CLK_REF_TSC]/tsc_delta); …
Run Code Online (Sandbox Code Playgroud)

performance x86 x86-64 cpu-architecture rdtsc

27
推荐指数
1
解决办法
1300
查看次数

获取CPU周期数?

我在SO上看到这篇文章,其中包含C代码以获取最新的CPU周期数:

基于CPU周期计算的C/C++ Linux x86_64中的分析

有没有办法在C++中使用这个代码(欢迎使用windows和linux解决方案)?虽然用C语言编写(而C是C++的一个子集)但我不太确定这段代码是否适用于C++项目,如果没有,如何翻译呢?

我使用的是x86-64

EDIT2:

找到此功能但无法让VS2010识别汇编程序.我需要包含任何内容吗?(我相信我必须换uint64_tlong long窗户......?)

static inline uint64_t get_cycles()
{
  uint64_t t;
  __asm volatile ("rdtsc" : "=A"(t));
  return t;
}
Run Code Online (Sandbox Code Playgroud)

EDIT3:

从上面的代码我得到错误:

"错误C2400:'操作码'中的内联汇编语法错误;找到'数据类型'"

有人可以帮忙吗?

c c++ performance x86 rdtsc

26
推荐指数
5
解决办法
4万
查看次数

"rdtsc"之前的"cpuid"

有时我会遇到使用rdtsc指令读取TSC的代码,但cpuid之前会调用.

为什么要打电话cpuid?我意识到这可能是与有TSC的值不同的内核,但什么究竟,当你调用序列这两个指令会发生什么?

x86 assembly rdtsc

18
推荐指数
2
解决办法
3826
查看次数

使用背靠背rdtsc进行负时钟周期测量?

我正在编写一个C代码,用于测量获取信号量所需的时钟周期数.我正在使用rdtsc,在对信号量进行测量之前,我连续两次调用rdtsc来测量开销.我在for循环中重复了这么多次,然后我将平均值用作rdtsc开销.

这是正确的,首先要使用平均值吗?

尽管如此,这里的一个大问题是,有时我会得到开销的负值(不一定是平均值,但至少是for循环中的部分值).

这也影响了连续计算sem_wait()操作所需的cpu周期数,有时也证明是负数.如果我写的不清楚,这里有一部分我正在编写的代码.

为什么我会得到这样的负值?


(编者注:请参阅获取CPU周期计数?以获得完整的64位时间戳的正确和可移植方式."=A"编译为x86-64时,asm约束只能得到低或高32位,具体取决于寄存器分配是否发生为uint64_t输出选择RAX或RDX .它不会选择edx:eax.)

(编辑的第二个注释:哎呀,这就是为什么我们得到负面结果的答案.仍然值得留下一个注释作为警告,不要复制这个rdtsc实现.)


#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>

static inline uint64_t get_cycles()
{
  uint64_t t;
           // editor's note: "=A" is unsafe for this in x86-64
  __asm volatile ("rdtsc" : "=A"(t));
  return t;
}

int num_measures = 10;

int main ()
{
   int i, value, res1, res2;
   uint64_t c1, c2;
   int tsccost, tot, a;

   tot=0;    

   for(i=0; i<num_measures; i++)
   { …
Run Code Online (Sandbox Code Playgroud)

c x86-64 overhead inline-assembly rdtsc

17
推荐指数
3
解决办法
1万
查看次数

为什么我应该在x86和x86_x64上使用'rdtsc'?

我知道rdtsc将处理器的时间戳计数器的当前值加载到两个寄存器中:EDX和EAX.为了在x86上获取它,我需要这样做(假设使用Linux):

    unsigned long lo, hi;
    asm( "rdtsc" : "=a" (lo), "=d" (hi));
    return lo;
Run Code Online (Sandbox Code Playgroud)

对于x86_x64:

        unsigned long lo, hi;
        asm( "rdtsc" : "=a" (lo), "=d" (hi) ); 
        return( lo | (hi << 32) );
Run Code Online (Sandbox Code Playgroud)

这是为什么?任何人都可以向我解释一下吗?

c cpu-registers rdtsc

16
推荐指数
2
解决办法
5430
查看次数

如何在GCC x86中使用RDTSC计算时钟周期?

使用Visual Studio,我可以从处理器读取时钟周期计数,如下所示.我如何与GCC做同样的事情?

#ifdef _MSC_VER             // Compiler: Microsoft Visual Studio

    #ifdef _M_IX86                      // Processor: x86

        inline uint64_t clockCycleCount()
        {
            uint64_t c;
            __asm {
                cpuid       // serialize processor
                rdtsc       // read time stamp counter
                mov dword ptr [c + 0], eax
                mov dword ptr [c + 4], edx
            }
            return c;
        }

    #elif defined(_M_X64)               // Processor: x64

        extern "C" unsigned __int64 __rdtsc();
        #pragma intrinsic(__rdtsc)
        inline uint64_t clockCycleCount()
        {
            return __rdtsc();
        }

    #endif

#endif
Run Code Online (Sandbox Code Playgroud)

c c++ x86 gcc rdtsc

15
推荐指数
4
解决办法
3万
查看次数

RDTSC开销的差异

我正在构建一个微基准来测量性能变化,因为我在一些原始图像处理操作中尝试使用SIMD指令内在函数.但是,编写有用的微基准测试很困难,因此我想首先了解(如果可能的话)消除尽可能多的变异和误差源.

我必须考虑的一个因素是测量代码本身的开销.我正在使用RDTSC进行测量,我正在使用以下代码来查找测量开销:

extern inline unsigned long long __attribute__((always_inline)) rdtsc64() {
    unsigned int hi, lo;
        __asm__ __volatile__(
            "xorl %%eax, %%eax\n\t"
            "cpuid\n\t"
            "rdtsc"
        : "=a"(lo), "=d"(hi)
        : /* no inputs */
        : "rbx", "rcx");
    return ((unsigned long long)hi << 32ull) | (unsigned long long)lo;
}

unsigned int find_rdtsc_overhead() {
    const int trials = 1000000;

    std::vector<unsigned long long> times;
    times.resize(trials, 0.0);

    for (int i = 0; i < trials; ++i) {
        unsigned long long t_begin = rdtsc64();
        unsigned long long t_end = rdtsc64(); …
Run Code Online (Sandbox Code Playgroud)

c++ performance assembly intel rdtsc

13
推荐指数
1
解决办法
4342
查看次数

在一个带有constant_tsc和nonstop_tsc的cpu上,为什么我的时间会漂移?

我在constant_tsc和cpu上运行这个测试nonstop_tsc

$ grep -m 1 ^flags /proc/cpuinfo | sed 's/ /\n/g' | egrep "constant_tsc|nonstop_tsc"
constant_tsc
nonstop_tsc
Run Code Online (Sandbox Code Playgroud)

第1步:计算tsc的滴答率:

我计算_ticks_per_ns了许多观测值的中位数.我用它rdtscp来确保按顺序执行.

static const int trials = 13;
std::array<double, trials> rates;

for (int i = 0; i < trials; ++i)
{
    timespec beg_ts, end_ts;
    uint64_t beg_tsc, end_tsc;

    clock_gettime(CLOCK_MONOTONIC, &beg_ts);
    beg_tsc = rdtscp();

    uint64_t elapsed_ns;
    do
    {
        clock_gettime(CLOCK_MONOTONIC, &end_ts);
        end_tsc = rdtscp();

        elapsed_ns = to_ns(end_ts - beg_ts); // calculates ns between two timespecs
    }
    while (elapsed_ns < …
Run Code Online (Sandbox Code Playgroud)

c++ linux rdtsc

9
推荐指数
2
解决办法
2030
查看次数