`
黑色杰克史密斯
  • 浏览: 16495 次
社区版块
存档分类
最新评论

rdtsc 指令测试 cpu 频率

 
阅读更多
#ifndef __TIMING__INCLUDED__IOSA_4__
#define __TIMING__INCLUDED__IOSA_4__

#include <crtdefs.h>  
#include <stdio.h>  
#include <windows.h>  
#include <mmsystem.h>  
  
#ifdef  __cplusplus  
extern "C" {  
#endif  
    _CRTIMP void __cdecl _wassert(_In_z_ const wchar_t* _Message, _In_z_ const wchar_t* _File, _In_ unsigned _Line);  
#ifdef  __cplusplus  
}  
#endif  
  
#define ENFORCE(_Expression) (void)((!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression),_CRT_WIDE(__FILE__),__LINE__),0))

static unsigned __int64 UisHnack, CpuFreq, MilliCpuFreq;

__declspec(naked) static unsigned __int64 LoadTSC ( void ) {
	__asm rdtsc
	__asm ret
}

__declspec(naked) static void TSleep ( unsigned int dwMilliseconds ) {
	
	static unsigned __int64 tStart;
	
	__asm {
		rdtsc 
		mov dword ptr [tStart], eax
		mov dword ptr [tStart+4], edx
		mov eax, 4[esp]
		mov dword ptr [UisHnack+4], 0
		mov dword ptr [UisHnack], eax	
	} 
	
	UisHnack *= MilliCpuFreq;
		
	while ( LoadTSC () - tStart <= UisHnack );

	__asm ret
}

static unsigned __int64 LoadSpecifyCpuFreq ( unsigned int CpuCoreIndex ) {

	unsigned __int64 timeStart64, cpu_fm64, timeToRDTSC, timeToQPF, Q_Error, QsecTCnt, pfq, lpQFCount;  
    unsigned __int32 OldPriClassFlags, OldPriThreadFlags;  
  
	HANDLE CurProcessHandle = GetCurrentProcess();  
    HANDLE CurThreadHandle  = GetCurrentThread ();
	
	OldPriClassFlags  = GetPriorityClass ( CurProcessHandle );  
    OldPriThreadFlags = GetThreadPriority( CurThreadHandle ); 
	
	ENFORCE ( CpuCoreIndex < 4 ); 
	ENFORCE ( SetThreadAffinityMask  ( CurThreadHandle,  ( (unsigned int) 1 << CpuCoreIndex ) ) );
	ENFORCE ( SetProcessAffinityMask ( CurProcessHandle, ( (unsigned int) 1 << CpuCoreIndex ) ) ); 
    ENFORCE ( QueryPerformanceFrequency ( ( (LARGE_INTEGER*) &pfq) ) );  
	ENFORCE ( SetPriorityClass ( CurProcessHandle, REALTIME_PRIORITY_CLASS ) );   
    ENFORCE ( SetThreadPriority( CurThreadHandle,  THREAD_PRIORITY_HIGHEST ) ); 
     
    __asm  { 
        rdtsc  	
        mov ebx, eax /* call rdtsc * 1 */ 
        mov ecx, edx 
		
        rdtsc  
		sbb edx, ecx
        sub eax, ebx 	
        mov dword ptr [timeToRDTSC], eax  
		mov dword ptr [timeToRDTSC+4], edx 
		
		rdtsc 
		mov dword ptr [timeToQPF], eax  
		mov dword ptr [timeToQPF+4], edx 
		
		push offset UisHnack
		call dword ptr [QueryPerformanceCounter]
		
		rdtsc
		sub eax, dword ptr [timeToQPF] 
		sbb edx, dword ptr [timeToQPF+4]  
		mov dword ptr [timeToQPF], eax
		mov dword ptr [timeToQPF+4], edx
		
		push offset UisHnack
		call dword ptr [QueryPerformanceCounter]
		
		lea  eax, QsecTCnt
		push eax
		call dword ptr [QueryPerformanceCounter]
		
		mov eax, dword ptr [UisHnack]   ; low 
		mov ebx, dword ptr [UisHnack+4] ; high	
		sub dword ptr [QsecTCnt], eax
		sbb dword ptr [QsecTCnt+4], ebx	
    }  
	
    QueryPerformanceCounter((LARGE_INTEGER*)&lpQFCount);  
  
    timeStart64 = lpQFCount;  
  
    __asm {
		rdtsc  
		mov dword ptr [cpu_fm64], eax  
		mov dword ptr [cpu_fm64+4], edx  
	}
  
    while ((Q_Error = (lpQFCount - timeStart64)) <= pfq )  
    {  
        QueryPerformanceCounter((LARGE_INTEGER*)&lpQFCount);  
    }   
	__asm {
		rdtsc    
		sub eax, dword ptr [cpu_fm64] 
		sbb edx, dword ptr [cpu_fm64+4]  
		mov dword ptr [cpu_fm64], eax
		mov dword ptr [cpu_fm64+4], edx
	}   
	MilliCpuFreq = ( CpuFreq = cpu_fm64 = cpu_fm64 - timeToQPF - timeToRDTSC - (unsigned __int64)( (double) ( Q_Error - pfq ) / (double) QsecTCnt * ( double ) timeToQPF ) ) / 1000;
	
    ENFORCE ( timeToRDTSC < 800 );  
    ENFORCE ( SetPriorityClass ( CurProcessHandle, OldPriClassFlags ) );   
    ENFORCE ( SetThreadPriority( CurThreadHandle,  OldPriThreadFlags ) );  

    return cpu_fm64;  
}

static unsigned __int64 SetFrame ( unsigned int FrameTicks, unsigned int CpuCoreIndex ) {
	return ( LoadSpecifyCpuFreq ( CpuCoreIndex ) / ( unsigned __int64 ) FrameTicks );
}
#endif



		.686                      ; create 32 bit code
		.mmx
		.xmm                     
		.model flat, stdcall      ; 32 bit memory model
		option casemap :none      ; case sensitive

; marco 		
	byt equ byte ptr
	wot equ word ptr
	dwot equ dword ptr
	
; extrn Windows API ...
	extrn exit:proc ; no WindowsAPI 
	extrn MessageBoxA@16:proc
	extrn GetPriorityClass@4:proc 
	extrn SetPriorityClass@8:proc 	
	extrn GetThreadPriority@4:proc 
	extrn SetThreadPriority@8:proc 
	extrn SetThreadAffinityMask@8:proc 
	extrn SetProcessAffinityMask@8:proc 
	extrn QueryPerformanceCounter@4:proc
	extrn QueryPerformanceFrequency@4:proc 

.data?
		__rdtsc_t dd 2 dup(?)
		__per_freq dd 2 dup(?) 	
		__time_temp1 dd 2 dup(?) 
		__time_temp2 dd 2 dup(?) 
		__time_temp3 dd 2 dup(?) 
		__time_temp4 dd 2 dup(?)
		__rdtsc_clock dd 2 dup(?)
		__per_counter_clock dd 2 dup(?)
		__per_counter_clock_plck dd 2 dup(?)
.code

__load_main_cpu_ticks proc C
					  option prologue:none, epilogue:none
		push 1
		push -2
		call SetThreadAffinityMask@8 
		cmp	eax, 0
		je	__exit
		
		push 1
		push -1
		call SetProcessAffinityMask@8 
		cmp	eax, 0
		je	__exit
		
		push 256
		push -1
		call SetPriorityClass@8 
		cmp	eax, 0
		je	__exit
		
		push 2
		push -2
		call SetThreadPriority@8
		cmp eax, -1
		je __exit
		
		push offset __per_freq
		call QueryPerformanceFrequency@4
	; main 
		mov	eax, 35600
		wait_some:		
			dec eax
			jne wait_some
		
			rdtsc 
			mov ecx, eax ; low 8 bit 
			rdtsc 
			sub eax, ecx ; low 8 bit sub ... 	
			mov dwot[__rdtsc_clock], eax 
			
			rdtsc 
			mov dwot[__rdtsc_t], eax 
			push offset __time_temp1 
			call QueryPerformanceCounter@4 
			
			rdtsc 
			sub eax, dwot[__rdtsc_t]
			sub eax, dwot[__rdtsc_clock]
			mov dwot[__per_counter_clock], eax 
			
			push offset __time_temp1
			call QueryPerformanceCounter@4 
			push offset __time_temp2
			call QueryPerformanceCounter@4 
			
			mov eax, dwot[__time_temp2]
			sub eax, dwot[__time_temp1]
			mov dwot[__per_counter_clock_plck], eax 
			
			rdtsc 
			mov dwot[__time_temp3], eax 
			mov dwot[__time_temp3+4], edx 
			push offset __time_temp1
			call QueryPerformanceCounter@4 
			mov eax, dwot[__time_temp1]
			mov edx, dwot[__time_temp1+4]	
			mov dwot[__time_temp2], eax 
			mov dwot[__time_temp2+4], edx 
			
	align 16
		main_loop:
			mov eax, dwot[__time_temp2]
			mov edx, dwot[__time_temp2+4]
			sub eax, dwot[__time_temp1] 
			sbb edx, dwot[__time_temp1+4] 
			cmp edx, dwot[__per_freq+4]
			ja __out_step 
			jb __in_step 
			sub eax, dwot[__per_freq]
			jae __out_step
			__in_step:
				push offset __time_temp2
				call QueryPerformanceCounter@4
				jmp main_loop			
	align 16 
		__out_step:	
			cvtsi2sd xmm0, eax 
			rdtsc 
			sub eax, dwot[__time_temp3]
			sbb edx, dwot[__time_temp3+4]
			sub eax, dwot[__rdtsc_clock]
			sbb edx, dwot[__rdtsc_clock+4]
			mov ecx, dwot[__per_counter_clock]
			shl ecx, 1 
			sub eax, ecx 
			sbb edx, 0		
			cvtsi2sd xmm2, dwot[__per_counter_clock]
			cvtsi2sd xmm1, dwot[__per_counter_clock_plck]
			divsd xmm2, xmm1 
			mulsd xmm2, xmm0 
			cvtsd2si ecx, xmm2
			sub eax, ecx 
			sbb edx, 0
			ret
			
		__exit:
			push 0
			push 0
			push 0 
			push 0
			call MessageBoxA@16
			push -1
			call exit 
			add esp, 4
			ret 		  

__load_main_cpu_ticks endp
	end

  • 大小: 21 KB
分享到:
评论

相关推荐

    RDTSC指令的应用之检测CPU主频

    这个操作可以是任何无副作用的计算,只要能确保在不同的CPU频率下,循环次数相同。 3. **再次获取时间戳**:在循环结束后,再执行一次RDTSC,获取结束时间戳,记为T2。 4. **计算时间差**:计算T2与T1的时间差ΔT...

    使用CPU时间戳进行高精度计时

    - **RDTSC指令**:与上述两个方法相比,RDTSC指令能够直接访问CPU的时间戳寄存器,提供更直接且高精度的时间测量方式。这种方法适用于需要极高精度的计时场景,特别是在循环体内的计时需求。 ##### 3. 高精度计时的...

    采用汇编和C两种语言,分别求取CPU当前的速度(RDTSC)

    总之,无论是使用汇编语言还是C语言,通过RDTSC指令都能有效地获取CPU当前的速度。这种方法对于性能测试、基准测试以及优化代码性能等方面具有重要意义。不过,要注意RDTSC的使用场景和潜在限制,以确保结果的准确性...

    编程检测CPU主频.pdf

    RDTSC指令是Intel 80386微处理器提供的一种特殊指令,它用于读取CPU的时间戳计数器,该计数器在每个时钟周期都会递增。RDTSC指令返回的结果分为两个部分,高32位存储在EDX寄存器,低32位存储在EAX寄存器。然而,为了...

    CPU 测速(MHz)和高精度延时(微秒级).rar_API 定时器_cpu测速71124_rdtsc_循环频率_高精度定时器

    利用 rdtsc 汇编指令可以得到 CPU 内部定时器的值, 每经过一个 CPU 周期, 这个定时器就加一。 如果在一段时间内数得 CPU 的周期数, CPU工作频率 = 周期数 / 时间 为了不让其他进程和线程打扰, 必需要设置最高的...

    用VC 编程实现对CPU主频的检测.pdf

    总结来说,通过VC++编程实现CPU主频检测,主要依赖于Intel 80386的RDTSC指令,结合Windows API函数和适当的界面设计,提供了一种简单易用的CPU主频检测方法,对于用户来说更加便捷。同时,使用汇编语言增强了程序的...

    TSC指令中文手册,TSC指令中文手册

    RDTSC指令用于无延迟地读取TSC,而RDTSCP指令则增加了保证在读取TSC之前所有之前指令完成执行的保证,这对于精确测量性能尤其有用。 手册还将涵盖TSC的可预测性问题。在某些处理器中,TSC可能会受到电源管理技术的...

    rdtsc:我的C ++包装器,辅助函数,摘要和实验

    `rdtsc`指令从CPU的Time-Stamp Counter寄存器中读取值,这个寄存器以处理器时钟周期为单位递增,通常与处理器的时钟频率同步。由于它是硬件级别的,因此不受操作系统调度、中断或其他软件层面的影响,能够提供微秒...

    CPU 的精确计时器

    1. RDTSC(Read Time-Stamp Counter):这是Intel CPU中的一种指令,可以直接读取CPU内部的计数器,提供自CPU启动以来的总时钟周期数。RDTSC是无中断的,因此对于高精度计时非常有用。 2. QueryPerformanceCounter...

    系统Timer机制,从硬件到操作系统,还有Qemu对timer的模拟

    - TSC(Time Stamp Counter):CPU内部的计数器,根据外部振荡器频率递增,可通过rdtsc指令读取。 - CPU Local Timer:类似于PIT,但仅对其处理器发送中断,频率取决于CPU FSB。 - HPET(High Precision Event ...

    C++中精确计时的方法

    随着现代CPU频率的提高,TSC能够提供非常高的时间分辨率,通常达到纳秒级别,这使得它成为实现高精度计时的理想选择。 #### RDTSC 指令 为了读取TSC中的值,Intel提供了RDTSC指令(Read Time Stamp Counter)。这...

    java脚本时钟源码-clocks:测试各种时钟的代码

    来检测 rdtscp 指令是否可用。 如果没有,它会绕过该代码(否则会抛出 SIGILL)。 您还可以传入 CPU 频率,单位为 GHz。 如果不这样做,则使用频率 1,这会为那些使用滴答计数的时钟源返回未修改的滴答计数(即,与 ...

    PC/XT 8253计数器PIT 芯片乐音开发应用

    《深入x86的内存寻址》I/O 外设硬件开发举例一.本包是原文《深入x86的内存寻址》I/O 寻址的充部分,提供PC...另外对芯片工作频率的探测也作了一定的深入,使用了CPUID、RDTSC 等指令来获取CPU硬件信息以适合程序需求。

    利用汇编获取代码运行时间

    需要注意的是,`RDTSC`指令的结果可能会受到CPU的超线程、频率变化等因素的影响,因此在多核或动态频率调整的环境中,可能需要额外的处理来确保时间测量的准确性。例如,可以使用`CPUID`指令来同步时钟周期计数器,...

    测试Context Switch time()

    这里需要注意的是,`rdtsc()` 的结果需要乘以每个时钟周期的实际时间(通常由处理器频率决定)才能转换为实际时间。 ### 四、总结 综上所述,通过上述两种方法可以有效地测量上下文切换的时间消耗。`gettimeofday...

    libcpuid-开源

    RDTSC指令则用于获取处理器的时钟周期,对于性能测试和基准测试尤为关键。 libcpuid库通过封装这些底层硬件指令,让开发者无需深入底层硬件细节就能获取到如处理器供应商、核心代号、支持的功能和指令集以及缓存...

    C++性能优化技术导论.pdf

    rdtsc指令可以提供更高的精度,即单个时钟周期,但需要注意其在多核CPU中的局限性,因为不同核心的周期可能不同。通过 sched_setaffinity 函数可以将进程绑定到特定的 CPU 核心上以提高计时的准确性。 1.2 分析性能...

    Windows下 VC 高精度计时和高频事件的产生

    - **RDTSC指令**:在x86/x64架构上,可以通过汇编语言直接调用处理器的Time Stamp Counter(TSC),获取CPU自启动以来的周期数。不过,由于不同CPU速度可能不同,跨CPU的比较需要谨慎处理。 2. **高频事件的产生**...

    计算程序运行时间.pdf计算程序运行时间.pdf计算程序运行时间.pdf

    RDTSC(Read Time Stamp Counter)是一个汇编指令,可以直接读取 CPU 的时间戳寄存器,其精度可以达到纳秒级别。 **示例代码**: ```c long hStart, lStart, hEnd, lEnd; long hCnt, lCnt; __asm { RDTSC mov ...

    最最精确计时

    2. **硬件定时器**:直接操作硬件定时器,如Intel的RDTSC(Read Time-Stamp Counter)指令,可以获取CPU时钟周期数。这种方法可以达到非常高的精度,但需要注意线程迁移和超线程的影响,因为这些情况可能导致RDTSC...

Global site tag (gtag.js) - Google Analytics