1.为什么会写windows下微秒级延时
测试memcpy的效率中,测试时间的拷贝效率在微秒级别,需要使用微秒级时间间隔计数。
windows下提供QueryPerformanceCounter(查询高性能计数器),QPC是基于硬件计数器,获取高分辨率时间戳。
参考:Acquiring high-resolution time stamps.aspx)
应用形式:
LARGE_INTEGER start, end;
LARGE_INTEGER Frequency;
QueryPerformanceFrequency(&Frequency);
QueryPerformanceCounter(&start);
//运行时间体
QueryPerformanceCounter(&end);
//转换时间(us) double(end.QuadPart - start.QuadPart) * 1000000 / Frequency.QuadPart
上面通过API查询高性能计数器,开始tick,结束tick,转换对应时间间隔。
2.基于QPC实现us延时
//timer.c
#include "timer.h"
static LARGE_INTEGER start;
static LARGE_INTEGER tick;
static LONGLONG SecondTick;
double GetMicrosecondTimeInterval(long long StartTick, long long EndTick, long long Frequency)
{
return (double)(EndTick - StartTick) * 1000000 / Frequency;
}
/*
* function:us延时初始化
*
* parameter:无
*
* return value:无
*
*/
void MicrosecondDelayInit(void)
{
LARGE_INTEGER frequence;
QueryPerformanceFrequency(&frequence);
SecondTick = frequence.QuadPart;
}
/*
* function:MicrosecondDelay();
* 实现微秒级延时
*
* parameter:
* n:延时的us数
*
* return value:
* 无
*/
void MicrosecondDelay(int n)
{
QueryPerformanceCounter(&start);
double endtick = SecondTick * n/1000000.0 + start.QuadPart;
for(;;)
{
QueryPerformanceCounter(&tick);
if (tick.QuadPart >= endtick)
break;
}
}
//timer.h
#pragma once //编译器保证头文件只编译一次
#include <windows.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
double GetMicrosecondTimeInterval(long long StartTick, long long EndTick, long long Frequency);
void MicrosecondDelayInit(void);
void MicrosecondDelay(int n);
#ifdef __cplusplus
}
#endif
3.us延时测试
1 #include <stdio.h>
2 #include <Windows.h>
3 #include"timer.h"
4
5 int main(void)
6 {
7 LARGE_INTEGER Frequency;
8 LARGE_INTEGER StartingTime, EndingTime;
9
10 QueryPerformanceFrequency(&Frequency);
11 MicrosecondDelayInit();
12
13 QueryPerformanceCounter(&StartingTime);
14 MicrosecondDelay(10);
15 QueryPerformanceCounter(&EndingTime);
16
17 printf("延时:%lf", GetMicrosecondTimeInterval(StartingTime.QuadPart, EndingTime.QuadPart, Frequency.QuadPart));
18 system("pause");
19 return 0;
20 }
测试情况:
1.延时情况能达到us级,多次测试运行,个别情况延时会有出入(出现情况较少)。
分析原因:
代码级影响较小,主要运行是在windows下,windows并不是实时操作系统,毕竟windows操作系统时间分辨率只能达到ms级。
延时可以被打断。cpu的频率会在变化,代码执行效率也会有影响。
2.这种延时效果明显好于Sleep的ms级延时。
4.windows下us延时,控制误差
1.硬件上实现us延时(这种情况对于不涉及底层硬件操作的并不现实)
2.既然windows提供给我们QPC(查询高性能计数器 <1us),配合着使用我们自己实现的us级延时。 我们延时前获取StartTick,延时结束后再获取EndTick,转换对应对应时间间隔。QueryPerformanceCounter函数2次消耗时间几乎可以忽略。通过打印我们可以看到us延时数。 大多数运行情况,延时函数效果1us内误差。大于1us延时我们可以剔除,保证1us时间误差。(这种做法是我们需要us级延时做测试时采用,保证后面数据结果在特定延时效果下)
5.总结
us延时常用于测试一些性能时使用。windows并未通过us级的延时函数。QPC是基于查询硬件计数器获取时间间隔,能达到us级别。