zoukankan      html  css  js  c++  java
  • windows下基于(QPC)实现的微秒级延时

    1.为什么会写windows下微秒级延时

    在上一篇 实现memcpy()函数及过程总结 中测试memcpy的效率中,测试时间的拷贝效率在微秒级别,需要使用微秒级时间间隔计数。

    windows下提供QueryPerformanceCounter(查询高性能计数器),QPC是基于硬件计数器,获取高分辨率时间戳。

    参考:Acquiring high-resolution time stamps

    应用形式:

     1 LARGE_INTEGER start, end;
     2 LARGE_INTEGER Frequency;
     3 QueryPerformanceFrequency(&Frequency);
     4  
     5 QueryPerformanceCounter(&start);
     6  
     7 //运行时间体
     8   
     9 QueryPerformanceCounter(&end);
    10   
    11 //转换时间(us) double(end.QuadPart - start.QuadPart) * 1000000 / Frequency.QuadPart

    上面通过API查询高性能计数器,开始tick,结束tick,转换对应时间间隔。

    2.基于QPC实现us延时

     1 //timer.c
     2
     3 #include "timer.h"
     4 
     5 static LARGE_INTEGER start;
     6 static LARGE_INTEGER tick;
     7 static LONGLONG SecondTick;
     8 
     9 double GetMicrosecondTimeInterval(long long StartTick, long long EndTick, long long Frequency)
    10 {
    11     return (double)(EndTick - StartTick) * 1000000 / Frequency;
    12 }
    13 
    14 /*
    15 *    function:us延时初始化
    16 *
    17 *    parameter:无
    18 *
    19 *    return value:无
    20 *                
    21 */
    22 void MicrosecondDelayInit(void)
    23 {
    24     LARGE_INTEGER frequence;
    25     QueryPerformanceFrequency(&frequence);
    26     SecondTick = frequence.QuadPart;    
    27 }
    28 
    29 /*
    30 *    function:MicrosecondDelay();
    31 *             实现微秒级延时
    32 *    
    33 *    parameter:
    34 *                n:延时的us数
    35 *    
    36 *    return value:
    37 *                无
    38 */
    39 
    40 void MicrosecondDelay(int n)
    41 {
    42     QueryPerformanceCounter(&start);
    43     double endtick = SecondTick * n/1000000.0 + start.QuadPart;
    44     for(;;)
    45     {
    46         QueryPerformanceCounter(&tick);
    47         if (tick.QuadPart >= endtick)
    48             break;
    49     }
    50 }
     1 //timer.h
     2 
     3 #pragma once        //编译器保证头文件只编译一次
     4 
     5 #include <windows.h>
     6 #include <stdio.h>
     7 
     8 #ifdef __cplusplus  
     9 extern "C" {
    10 #endif 
    11     double GetMicrosecondTimeInterval(long long StartTick, long long EndTick, long long Frequency);
    12     void MicrosecondDelayInit(void);
    13     void MicrosecondDelay(int n);
    14 #ifdef __cplusplus  
    15 }
    16 #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级别。

            

  • 相关阅读:
    javaSE第二十四天
    javaSE第二十三天
    javaSE第二十二天
    javaSE第二十一天
    javaSE第二十天
    javaSE第十九天
    python020 Python3 OS 文件/目录方法
    python019 Python3 File(文件) 方法
    python018 Python3 输入和输出
    python017 Python3 模块
  • 原文地址:https://www.cnblogs.com/chuanfengzhang/p/8453671.html
Copyright © 2011-2022 走看看