__inline__ uint64_t rdtsc() {
uint32_t low, high;
__asm__ __volatile__ (
"xorl %%eax,%%eax \n cpuid"
::: "%rax", "%rbx", "%rcx", "%rdx" );
__asm__ __volatile__ (
"rdtsc" : "=a" (low), "=d" (high));
return (uint64_t)high << 32 | low;
}
Run Code Online (Sandbox Code Playgroud)
我在程序中使用了上面的rdtsc函数作为计时器:以下代码导致312-344个时钟周期:
start = rdtsc();
stop = rdtsc();
elapsed_ticks = (unsigned)((stop-start));
printf("\n%u ticks\n",elapsed_ticks);
Run Code Online (Sandbox Code Playgroud)
每次运行上面的代码我都会得到不同的值.这是为什么?
我在Visual C++中运行相同的代码,它在"intrin.h"中使用了rdtsc函数.我得到了18个时钟的恒定值.是的,每次运行都是恒定的!有人可以解释一下吗?谢谢!
我试图将别人的项目从32位转换为64位.除了一个函数外,一切似乎都没问题,它使用了构建x64时Visual Studio不支持的汇编表达式:
// Returns the Read Time Stamp Counter of the CPU
// The instruction returns in registers EDX:EAX the count of ticks from processor reset.
// Added in Pentium. Opcode: 0F 31.
int64_t CDiffieHellman::GetRTSC( void )
{
int tmp1 = 0;
int tmp2 = 0;
#if defined(WIN32)
__asm
{
RDTSC; // Clock cycles since CPU started
mov tmp1, eax;
mov tmp2, edx;
}
#else
asm( "RDTSC;\n\t"
"movl %%eax, %0;\n\t"
"movl %%edx, %1;"
:"=r"(tmp1),"=r"(tmp2)
:
:
);
#endif
return ((int64_t)tmp1 …Run Code Online (Sandbox Code Playgroud) 我正在实现一些数据结构,其中我需要在一段时间后使某些条目无效,因此对于每个条目,我需要维护其插入时间戳。当我得到一个条目时,我需要再次获取时间戳并计算从插入开始的经过时间(如果它太旧,我无法使用它)。
许多线程高度满足此数据结构,因此我必须以最有效的方式获取此时间戳(oninsert和find)。效率在这里非常重要。
如果重要的话,我正在使用 C++ 开发的 linux 机器上工作。检索时间戳的最有效方法是什么?
顺便说一句,在我正在做的一些旧项目中,我记得我看到了一些直接从 CPU 获取时间戳的汇编命令(不记得命令了)。
我是C ++和基准测试的新手
我不明白这段代码的作用是什么?因此,我找到了一些有关edx,eax寄存器的信息,但是我不完全了解它如何在代码中发挥作用。所以我理解这段代码本质上返回了cpu周期的当前滴答声。因此,它是否将当前的滴答存储在寄存器中,一部分存储在hi中,另一部分存储在lo中。并且,“ = a”和“ = d”是否指定将其存储在哪个寄存器中。
将其分为两个部分的意义何在?
"rdtsc" : "=a" (lo), "=d" (hi)
Run Code Online (Sandbox Code Playgroud)
上下文中的代码:
int64_t rdtsc(){
unsigned int lo,hi;
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return ((uint64_t)hi << 32) | lo;
}
Run Code Online (Sandbox Code Playgroud) 我曾经使用 rdtsc 对 Linux 系统调用进行基准测试,以获取系统调用前后的计数器差异。我将结果解释为挂钟定时器,因为 TSC 以恒定速率递增,并且在进入暂停状态时不会停止。
不变 TSC 概念描述为
不变的 TSC 将在所有 ACPI P-、C- 中以恒定速率运行。和 T 状态。
当状态从 C0(运行)更改为 C1(停止)时,恒定非不变tsc 是否可以改变频率?
我当前的观点是,它不能仅在性能(P)状态下更改频率。因此,在使用非不变 tsc 时,应用 rdtsc 获取用于系统调用的挂钟计时器并不可靠。
我在 my 中没有找到不变的 tsc 标志/proc/cpuinfo,只是constant_tsc意味着它没有必要不变。
混乱的根源是英特尔系统编程手册中的一句话:
较新处理器中的时间戳计数器可能支持增强功能,称为不变 TSC。
所以有些芯片(包括我的)具有恒定的 tsc,但不是不变的。
我很困惑rdtscp在多核环境中是否单调递增。根据文档:__rdtscp,rdtscp似乎是基于处理器的指令,可以防止围绕调用重新排序指令。
处理器在每个时钟周期单调递增时间戳计数器 MSR,并在处理器复位时将其复位为 0。
rdtscp肯定会在同一个 CPU 内核上单调递增,但是这个rdtscp时间戳是否保证在不同的 CPU 内核上是单调的?我相信没有这种绝对的保证。例如,
Thread on CPU core#0 Thread on CPU core#1
unsigned int ui;
uint64_t t11 = __rdtscp(&ui);
uint64_t t12 = __rdtscp(&ui);
uint64_t t13 = __rdtscp(&ui);
unsigned int ui;
uint64_t t21 = __rdtscp(&ui);
uint64_t t22 = __rdtscp(&ui);
uint64_t t23 = __rdtscp(&ui);
Run Code Online (Sandbox Code Playgroud)
以我的理解,我们可以有一个决定性的结论t13 > t12 > t11,但我们不能保证t21 > t13。
我想写一个脚本来测试我的理解是否正确,但我不知道如何构建一个例子来验证我的假设。
// file name: rdtscptest.cpp
// g++ rdtscptest.cpp -g -lpthread -Wall -O0 -o …Run Code Online (Sandbox Code Playgroud) 我编写了一个简单的程序来使用 RDTSC 指令测量代码执行时间。但是我不知道我的结果是否正确以及我的代码是否有问题......我不知道如何验证它。
#include <stdio.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#define N (1024*4)
unsigned cycles_low, cycles_high, cycles_low1, cycles_high1;
static __inline__ unsigned long long rdtsc(void)
{
__asm__ __volatile__ ("RDTSC\n\t"
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t": "=r" (cycles_high), "=r" (cycles_low)::
"%rax", "rbx", "rcx", "rdx");
}
static __inline__ unsigned long long rdtsc1(void)
{
__asm__ __volatile__ ("RDTSC\n\t"
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t": "=r" (cycles_high1), "=r" (cycles_low1)::
"%rax", "rbx", "rcx", "rdx");
}
int main(int argc, char* argv[])
{
uint64_t start, end;
rdtsc();
malloc(N); …Run Code Online (Sandbox Code Playgroud) 我编写了一个计时函数,记录了函数的运行时间,并计算了多次运行的均值和标准差。我惊讶地发现即使是看似简单的任务(例如加两个双打)也有很高的标准偏差。我分析了python中的数据(请参见图)。C ++输出是19.6171 ns +/- 21.9653ns (82799807 runs)使用以下命令编译的:
gcc version 8.3.0 (Debian 8.3.0-19)
/usr/bin/c++ -O3 -DNDEBUG -std=gnu++17
Run Code Online (Sandbox Code Playgroud)
整个测试是在我的个人计算机上完成的,该计算机不是空闲的而是运行DE,浏览器,IDE和其他进程。测试期间有可用的RAM。我的带有HT的双核CPU空闲率低于10%。
在这种情况下,是否会出现从20 ns的平均值到50 µs的峰值?
运行时间图
这是的内容std::vector<double> run_times。我没有看到任何图案。

定时
gcc version 8.3.0 (Debian 8.3.0-19)
/usr/bin/c++ -O3 -DNDEBUG -std=gnu++17
Run Code Online (Sandbox Code Playgroud)
计时文件
#include <cstdint>
#include <ostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <chrono>
#include <numeric>
#include <fstream>
struct TimingResults{
// all time results are in nanoseconds
double mean;
double standard_deviation;
uint64_t number_of_runs;
};
std::ostream& operator<<(std::ostream& os, const TimingResults& results);
template …Run Code Online (Sandbox Code Playgroud)