2

gettimeofday()を使用してマイクロ秒を継続的に出力しています。プログラム出力に示されているように、時間はマイクロ秒間隔で更新されるのではなく、特定のサンプルに対して繰り返され、マイクロ秒ではなくミリ秒単位で増加することがわかります。

while(1)
{
  gettimeofday(&capture_time, NULL);
  printf(".%ld\n", capture_time.tv_usec);
}

プログラム出力:

.414719
.414719
.414719
.414719
.430344
.430344
.430344
.430344

 e.t.c

次のように、出力を順番にインクリメントしたい。

.414719
.414720
.414721
.414722
.414723

また

.414723, .414723+x, .414723+2x, .414723 +3x + ...+ .414723+nx

Capture_time.tv_usecから取得した場合、マイクロ秒が更新されていないようです。

=================================//完全なプログラム

#include <iostream>
#include <windows.h>
#include <conio.h>
#include <time.h>
#include <stdio.h>

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
#else
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
#endif

struct timezone 
{
  int  tz_minuteswest; /* minutes W of Greenwich */
  int  tz_dsttime;     /* type of dst correction */
};

timeval capture_time;  // structure

int gettimeofday(struct timeval *tv, struct timezone *tz)
{
  FILETIME ft;
  unsigned __int64 tmpres = 0;
  static int tzflag;

  if (NULL != tv)
  {
    GetSystemTimeAsFileTime(&ft);

    tmpres |= ft.dwHighDateTime;
    tmpres <<= 32;
    tmpres |= ft.dwLowDateTime;

    /*converting file time to unix epoch*/
    tmpres -= DELTA_EPOCH_IN_MICROSECS; 
    tmpres /= 10;  /*convert into microseconds*/
    tv->tv_sec = (long)(tmpres / 1000000UL);
    tv->tv_usec = (long)(tmpres % 1000000UL);
  }

  if (NULL != tz)
  {
    if (!tzflag)
    {
      _tzset();
      tzflag++;
    }

    tz->tz_minuteswest = _timezone / 60;
    tz->tz_dsttime = _daylight;
  }

  return 0;
}

int main()
{
   while(1)
  {     
    gettimeofday(&capture_time, NULL);     
    printf(".%ld\n", capture_time.tv_usec);// JUST PRINTING MICROSECONDS    
   }    
}
4

4 に答える 4

7

観測される時間の変化は、0.414719 秒から 0.430344 秒です。その差は 15.615 ミリ秒です。数値の表現がマイクロ秒であるという事実は、それが 1 マイクロ秒ずつインクリメントされるという意味ではありません。実際、私は 15.625 ミリ秒を期待していました。これは、標準ハードウェアでのシステム時間の増分です。私はここここで詳しく調べました。これは、システム時間の粒度と呼ばれます。

ウィンドウズ:

ただし、これを改善する方法、粒度を減らす方法があります: The Multimedia Timers。特に、タイマー分解能の取得と設定では、システムの割り込み頻度を増やす方法が明らかになります。

コード:

#define TARGET_PERIOD 1         // 1-millisecond target interrupt period


TIMECAPS tc;
UINT     wTimerRes;

if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) 
// this call queries the systems timer hardware capabilities
// it returns the wPeriodMin and wPeriodMax with the TIMECAPS structure
{
  // Error; application can't continue.
}

// finding the minimum possible interrupt period:

wTimerRes = min(max(tc.wPeriodMin, TARGET_PERIOD ), tc.wPeriodMax);
// and setting the minimum period:

timeBeginPeriod(wTimerRes); 

これにより、システムは最大割り込み頻度で実行されます。結果として、システム時間の更新もより頻繁に発生し、システム時間の増分の粒度はclose to 1 milisecondほとんどのシステムで異なります。

これを超える解像度/粒度に値する場合は、 QueryPerformanceCounterを調べる必要があります。ただし、長期間使用する場合は注意が必要です。このカウンターの頻度は、QueryPerformanceFrequencyへの呼び出しによって取得できます。OS はこの頻度を定数と見なし、常に同じ値を返します。ただし、一部のハードウェアはこの周波数を生成し、実際の周波数は指定された値とは異なります。オフセットがあり、熱ドリフトを示しています。したがって、誤差は数マイクロ秒/秒から数マイクロ秒/秒の範囲であると想定されます。詳細については、上記の 2 番目の「こちら」リンクを参照してください。

Linux:

Linux の場合、状況は多少異なります。アイデアを得るためにこれを見てください。Linux は、関数getnstimeofday (エポックからの秒数) を使用した CMOS クロックの情報と、関数timekeeping_get_nsを使用した高周波カウンター (マイクロ秒) からの情報を混合します。両方のソースが異なるハードウェアによってサポートされているため、これは些細なことではなく、精度の点で疑問があります。2 つのソースはフェーズ ロックされていないため、1 秒あたり 100 万マイクロ秒を超える/下回る可能性があります。

于 2012-11-01T11:42:59.020 に答える
1

<chrono>C++11ヘッダーを確認することをお勧めします。

high_resolution_clock(C++11) 利用可能な最短ティック周期のクロック

ここでいうティック周期とは、クロックが更新される頻度です。詳細を見ると:

template<
     class Rep,
     class Period = std::ratio<1>
> class duration;

クラス テンプレートstd::chrono::durationは時間間隔を表します。

これは、タイプ Rep のティック数とティック期間で構成されます。ティック期間は、あるティックから次のティックまでの秒数を表すコンパイル時の有理定数です。

以前は、 のような関数gettimeofdayはマイクロ秒で表現された時間を提供していましたが、この時間表現が更新された間隔をまったく伝えていませんでした。

C++11 標準では、この情報が明確になり、時間を表す単位とティック周期の間に関係がないことが明らかになりました。したがって、両方を考慮に入れる必要があります。

ティック期間は、それに近い期間を測定する場合に非常に重要です。測定したい期間がティック期間よりも劣っている場合は、観察したように「離散的に」測定します: 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, ... この時点で注意を促します。

于 2012-11-01T14:15:12.017 に答える
1

Windows のシステム クロックは数ミリ秒ごとにしか刻みません。あなたのケースでは 1 秒あたり 64 回なので、刻むとシステム時間が 15.625 ミリ秒増加します。

解決策は、システム時間 ( QueryPerformanceCounter) よりも精度の高いタイマーを使用することです。

ただし、.414723、.414723+x、.414723+2x、.414723 +3x + ...+ .414723+nx は表示されません。これは、コードがxマイクロ秒ごとに正確に実行されるわけではないためです。可能な限り高速に実行されますが、常に一定の速度である必要がある、または一定の速度である場合はマイクロ秒の整数値であるという特別な理由はありません。

于 2012-11-01T11:46:52.830 に答える
0

これは、コードを実行するプロセスが常に実行されるようにスケジュールされているとは限らないためです。

それが行われている間、それはループをすばやく回って、マイクロ秒ごとに複数の値を出力します。これは、最新の CPU では比較的長い時間です。

その後、システムによって実行がスケジュールされていない期間があり、そのため値を出力できません。

マイクロ秒ごとに実行したい場合は、高性能ハードウェアで実行されている一部のリアルタイム オペレーティング システムで実行できる可能性があります。

于 2012-11-01T11:04:07.477 に答える