0

while ループと関数の順序を次のように指定します。

int k=0;
int total=100;
while(k<total){
   doSomething();
   if(approx. t milliseconds elapsed) { measure(); }
   ++k;
}

t ミリ秒ごとに「測定」を実行したい。ただし、「doSomething」は最後の実行から t 番目のミリ秒に近い可能性があるため、最後の測定から約 t ミリ秒経過した後に測定を実行しても問題ありません。私の質問は次のとおりです。これはどのように達成できますか?

1 つの解決策は、タイマーをゼロに設定し、すべての「doSomething」の後に測定することです。許容範囲内であれば、対策を行い、リセットします。ただし、そのようなタスクにどの C++ 関数を使用する必要があるかはわかりません。このように、いくつかの機能がありますが、どれが最も適切かという議論は私の理解外です。一部の関数は実際には他のプロセスにかかる時間を考慮に入れていることに注意してください。ただし、タイマーは C++ コードの実行時間のみを測定する必要があります (明確であることを願っています)。もう 1 つのことは、以下に指摘するように、測定の解像度です。提案された中程度のオプションを考えてみましょう。

4

1 に答える 1

2

高解像度のタイミングはプラットフォーム固有であり、質問で指定していません。標準ライブラリの clock() 関数は、毎秒 CLOCKS_PER_SEC でインクリメントするカウントを返します。一部のプラットフォームでは、必要な解像度を得るのに十分な速さである場合がありますが、実装で定義されているため、システムのティック レートを確認する必要があります。ただし、十分に高い場合は、次のようにします。

#define SAMPLE_PERIOD_MS 100
#define SAMPLE_PERIOD_TICKS ((CLOCKS_PER_SEC * SAMPLE_PERIOD_MS) / 1000)

int k=0;
int total=100;
clock_t measure_time = clock() + SAMPLE_PERIOD_TICKS  ;
while(k<total)
{
   doSomething();
   if( clock() - measure_time > 0 )
   { 
        measure(); 
        measure_time += SAMPLE_PERIOD_TICKS ;
        ++k;
   }
}

必要に応じて、clock() を他の高解像度クロック ソースに置き換えることができます。

ただし、いくつかの問題に注意してください。このメソッドは「ビジー ループ」です。doSomething() または measure() のいずれかが CPU を生成しない限り、プロセスは可能な限りすべての CPU サイクルを使用します。これがターゲットで実行されている唯一のコードである場合、それは問題ではない可能性があります。一方、これがリアルタイムではない Windows や Linux などの汎用 OS で実行されている場合、プロセスが他のプロセスによってプリエンプトされる可能性があり、これがサンプリング周期の精度に影響を与える可能性があります。正確なタイミングが必要な場合は、RTOS を使用し、doSomething() と measure() を別々のスレッドで実行することをお勧めします。より良いGPOSでも。たとえば、一般的なパターン (仕様がない場合に作成された API を使用する) は次のようになります。

int main()
{
    StartThread( measure_thread, HIGH_PRIORITY ) ;
    for(;;)
    {
        doSomething() ;
    }
}

void measure_thread()
{
    for(;;)
    {
        measure() ;
        sleep( SAMPLE_PERIOD_MS ) ;
    }
}

のコードは、実行にほとんど時間がかからないmeasure_thread()場合にのみ正確です。measure()かなりの時間がかかる場合は、それを考慮する必要があります。非決定論的である場合は、スリープ期間を差し引くために実行時間を測定する必要がある場合もあります。

于 2012-06-02T16:35:13.017 に答える