2

何を検索すればよいかさえわからないため、何かに問題があり、それについての答えが見つかりませんでした。アプリケーションから QueryPerformanceCounter を使用してタイマー クラスを作成しました。独自のインスタンス化されたタイマーを持つ 2 番目のスレッド オブジェクトを起動し、タイマーからデルタ時間を取得し、それを使用してループの反復回数を出力する無限ループを作成しました。 2番目。

奇妙な値を与えていることに気付いたので、デルタ時間を出力し始め、時々0になることがわかったので、デルタ時間を返すメソッドに入り、いくつかのテストを行いました。これは私の deltaTime() メソッドです:

    double MyTimer2::deltaTime()
    {
        LARGE_INTEGER timenow;
        QueryPerformanceCounter(&timenow);
        //std::cout << "timenow=" << (double)timenow.QuadPart << "   currentticks=" << (double)m_currentTicks.QuadPart << std::endl;

        double m_deltaTime = (double)(timenow.QuadPart - m_currentTicks.QuadPart) /* 1000.0*/ / (double)m_frequency.QuadPart;

        m_currentTicks = timenow;

        if(m_deltaTime < 0.000001)
            return 0.0;

        return m_deltaTime;
    }

そこで、「return 0.0;」にブレークポイントを設定しました。そして何が起こるかというと、ほとんどの場合そこに到達しますが、これは正しくありません。ただし、印刷コードのコメントを外して実行すると、ブレークポイントで停止することはありません。したがって、理論的には、私の印刷コードは正しく機能していますが、それを削除すると、正常に機能しなくなります! これはどのように可能であり、なぜ起こっているのでしょうか?どうすれば修正できますか? _ReadWriteBarrier() を試しましたが失敗しました。

前もって感謝します!

編集: 物理シミュレーション用の高解像度タイマーが必要です!

4

3 に答える 3

3

数世代前のプロセッサQueryPerformanceCounter()は、CPU のサイクル カウンタを読み取ります (例: rdtsc)。この方法を使用すると、連続した読み取りからのティック数がゼロになることはありません。分解能は、CPU クロック レートと同じで、たとえば 3 GHz でした。

最新のプロセッサには、サイクル カウンタをタイミングに役立たなくする 2 つの特性があります。まず、複数のコアがあり、それぞれに独自のサイクル カウンターがあります。スレッドはコア間で移行できます。2 つの異なるコアからサイクル カウンターを読み取った場合、その差は経過時間とは関係ありません。マイナスになることさえあります。第 2 に、負荷に基づく動的クロッキング (電力を節約するためのアンダークロッキングとパフォーマンスのためのオーバークロッキングの両方) があります。Intel では、これらをそれぞれ「SpeedStep」と「Turbo Boost」と呼んでいます。サイクル レートが固定されていない場合、ティックから時間に変換する方法はありません。

そのため、QueryPerformanceCounter数 MHz の分解能を持つ高性能イベント カウンター (HPET) と呼ばれる専用のハードウェアを使用するようになりました。重要なのは、コアの数に関係なく 1 つだけであり、速度が動的に変化しないことです。ただし、解像度が低いため、ティック間で 2 回読み取ることができるようになりました。この場合、経過時間がゼロとして報告されます。

実際には、これは問題ではありません。HPET が提供できるよりも正確なタイミングが必要な場合は、汎用コンピューターは適していません。ナノ秒範囲のタイミングは、割り込みによって深刻な影響を受けます。

于 2012-04-29T16:36:42.283 に答える
1

まず第一に、あなたのタイマーは間違っています:それはあなたのCPUを集中的に消費します。シングルコアマシンでは、すべてのシステムの速度が低下します。タイマーを作成してWindowsをターゲットにする場合は、タイマー関数を使用できます。

次に、関数によって返される負ではないすべての値deltaTime()が有効です。リアルタイムオペレーティングシステムでホストしていない場合、すべての操作に任意の​​時間がかかる可能性があります。1回の反復には、プロセッサティックの約数十サイクルまたは数十年かかる場合があります。誰も保証しません。

第三に、実験結果について。コンテキストが2つの連続する時間測定の間で一度切り替えられる場合、約0.016sの値が得られるようです。そうでない場合は、以下の値が得られ0.000001sます0s

言われたように、コンソールへの印刷は比較的重い操作であり、それを有効にすると、実際には常にコンテキストが切り替えられます。

編集

QueryPerformanceCounter優れた解像度を提供しているように見えますが、それはあなたを閉じ込めます。リアルタイムOSで作業しない限り、実際に高解像度のタイマーを取得することはありません。

于 2012-04-29T15:57:32.360 に答える
1

このブロックの目的は何でしょうか?

if(m_deltaTime < 0.000001)
    return 0.0;

それには価値がなく、結果を単純にねじ込み、実際にはそうではなかったのに時間がゼロであったことを示します。

于 2012-04-29T16:02:02.720 に答える