2012-12-07 55 views
16

只见所以这个帖子里面包含了C代码以获得最新的CPU周期数:获取CPU周期数?

CPU Cycle count based profiling in 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; 
} 

EDIT3:

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

"error C2400: inline assembler syntax error in 'opcode'; found 'data type'"

可能有人请帮助?

+1

“C++是C的一个子集” - 你的意思是,其他各地的办法吗? – Mysticial

+0

@Mysticial yup :)编辑 – user997112

+0

Visual Studio不支持x86-64上的程序集。 –

回答

41

直接拉我的项目之一:

#include <stdint.h> 

// Windows 
#ifdef _WIN32 

#include <intrin.h> 
uint64_t rdtsc(){ 
    return __rdtsc(); 
} 

// Linux/GCC 
#else 

uint64_t rdtsc(){ 
    unsigned int lo,hi; 
    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); 
    return ((uint64_t)hi << 32) | lo; 
} 

#endif 
+0

这是打包它的好方法。 –

+0

谢谢神秘 – user997112

+8

FWIW,GCC 4.5和更新包括__rdtsc() - #包括得到它。头文件还包含微软的中的许多其他intel内部函数,并且当您包含大多数SIMD头文件(emmintrin.h,xmmintrin.h等)时,默认情况下默认包含它。 – jstine

5

对于Windows,Visual Studio提供了一个方便的“编译器的内部”(即一个特殊的功能,它在编译器能),其执行RDTSC指令给你,给你回结果:

unsigned __int64 __rdtsc(void); 
6

VC++采用了内联汇编完全不同的语法 - 但仅限于32位版本。 64位编译器根本不支持内联汇编。

在这种情况下,这可能是一样好 - rdtsc有(至少),当涉及到时间的代码序列两大问题。首先(最喜欢的指令),它可以乱序执行,因此,如果你想一次简短的代码序列,之前和代码后rdtsc可能都在它之前执行,或两者之后,或有什么你(我相当肯定这两个人总是会按照彼此的顺序执行,所以至少这种差别永远不会是负面的)。

其次,多芯(或多处理器)系统上,一个RDTSC可能在一个核心/处理器和其它在不同的核心/处理器执行。在这种情况下,负面结果完全可能是

一般来说,如果你想在Windows下一个精确的计时器,你会更好使用QueryPerformanceCounter

如果你真的坚持使用rdtsc,我相信你必须在完全用汇编语言编写的单独模块中完成(或者使用编译器内部),然后与你的C或C++链接。我从来没有写的64位模式下的代码,但在32位模式下,它看起来是这样的:

xor eax, eax 
    cpuid 
    xor eax, eax 
    cpuid 
    xor eax, eax 
    cpuid 
    rdtsc 
    ; save eax, edx 

    ; code you're going to time goes here 

    xor eax, eax 
    cpuid 
    rdtsc 

我知道这看起来很奇怪,但它实际上是正确的。您执行CPUID是因为它是序列化指令(不能按顺序执行),并且在用户模式下可用。在开始计时之前,您需要执行三次,因为英特尔记录了第一次执行可以/以不同于第二次执行的速度运行的事实(并且他们推荐的是三次,所以三次)。

然后你执行你的测试代码,另一个cpuid强制序列化,最后rdtsc获得代码完成后的时间。除此之外,你希望使用你的操作系统提供的任何方法来强制这些操作在一个进程/内核上运行。在大多数情况下,您还希望强制代码对齐 - 对齐方式的更改可能会导致执行语句中的相当大的差异。

最后,你想多次执行它 - 它总是有可能在事情中间被中断(例如任务切换),所以你需要为执行的可能性做好准备比其他时间花费的时间要长得多 - 例如,5次运行需要大约40-43个时钟周期,第6次运行需要10000+个时钟周期。显然,在后一种情况下,你只是抛出异常值 - 这不是来自你的代码。

摘要:管理执行rdtsc指令本身(几乎)是您最担心的问题。有相当多的你需要做之前,你可以从rdtsc结果实际上将意味着什么。

+0

我敢肯定,当我研究它,我发现文件是'QueryPerformanceCounter'(这是在'rdtsc'薄薄的面纱),从你在多核/多处理器系统中确定的相同问题的困扰。但我想我也发现这个问题在早期系统中是一个真正的问题,因为大多数BIOS甚至没有尝试同步不同核心上的计数器,但是大多数较新的BIOS(可能不算便宜的垃圾机器BIOS)确实会使努力,所以他们现在可能只有少数几个。 – phonetagger

+0

....但是为了完全避免这种可能性,您可以设置线程的处理器关联掩码,以便它仅在单个内核上运行,从而完全消除此问题。 (我看你也提到过) – phonetagger

+0

QPC可以但不一定是rdtsc上的一块薄薄的面纱。至少在同一时间,单处理器内核使用rdtsc,但多处理器内核使用主板的1.024 MHz时钟芯片(正是出于上述原因)。 –