4

C++ で何かを C# と同じくらい正確に測定するにはどうすればよいですか?

これは私のC#コードです

var elapsedMilliseconds = (double)(sw.ElapsedTicks * 1000L) / Stopwatch.Frequency;

ビジュアルスタジオ2010を使用しています。

4

5 に答える 5

14

C# の Stopwatch クラスは、C/C++ から呼び出すことができる次の 2 つの Win32 API 呼び出しに基づいています。

最初の関数を呼び出し、それを 2 番目の関数で割り、秒単位の値を取得します。

例:

LARGE_INTEGER freq, start, end;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&start);
// do some long operation here
Sleep(5000);
QueryPerformanceCounter(&end);
// subtract before dividing to improve precision
double durationInSeconds = static_cast<double>(end.QuadPart - start.QuadPart) / freq.QuadPart;

ドキュメント内の次のコメントは実際のものであり、考慮する必要があることに注意してください。私は、VirtualBox 仮想マシンでこの動作を個人的に観察しています。異なるプロセッサ間で数十ミリ秒の違いが存在する可能性があり、負の持続時間や予想よりも長い持続時間などの予期しない結果につながります。

マルチプロセッサ コンピュータでは、どのプロセッサが呼び出されるかは重要ではありません。ただし、基本入出力システム (BIOS) またはハードウェア アブストラクション レイヤー (HAL) のバグにより、異なるプロセッサでは異なる結果が得られる可能性があります。スレッドのプロセッサ アフィニティを指定するには、SetThreadAffinityMask 関数を使用します。

詳細については、これに興味があるかもしれません: System.Diagnostics.Stopwatch は Elapsed... プロパティに負の数を返します

上記の 2 つの API を使用できない場合、または失敗コードを返す場合、Stopwatch クラスは GetTickCount にフォールバックすることに注意してください。これはおそらく Windows 9x との互換性を維持するためです。最新の PC でこれらの API を使用して問題が発生したことはありません。ただし、GetTickCount には必要な精度がありません。

于 2013-01-10T14:35:15.590 に答える
1

もっと具体的な測定が必要だったので、見つけました。他の答えのThx。それらはすべて良いです。この回答で、必要に応じて簡単にマイクロ秒に切り替えることができます。

もちろん、素晴らしい説明と人々のフィードバックがあるため、James Johnstonの回答を正しいものとして受け入れます。

ありがとう

int main(int argc, char ** argv)
{
unsigned long long nFreq = GetPerformanceTicksInSecond();
unsigned long long nBefore = GetPerformanceTicks();
timer start1 = timer::start();

CallSomeFunction();

unsigned long long nAfter = GetPerformanceTicks();
const unsigned long long nDiff = nAfter - nBefore;
const unsigned long long nMicroseconds = GetTickMicroseconds(nDiff,nFreq);

cout << "CallSomeFunction() took " << nMicroseconds << " " << time << endl;

return 0;

}

unsigned long long GetPerformanceTicks()
{
    LARGE_INTEGER nValue;

    ::QueryPerformanceCounter(&nValue);

    return nValue.QuadPart;
}

unsigned long long GetPerformanceTicksInSecond()
{
    LARGE_INTEGER nFreq;

    ::QueryPerformanceFrequency(&nFreq);

    return nFreq.QuadPart;
}

double GetTickSeconds(unsigned long long nTicks,unsigned long long nFreq)
{
    return static_cast<double>(nTicks) / static_cast<double>(nFreq);
}

unsigned long long GetTickMilliseconds(unsigned long long nTicks,unsigned long long nFreq)
{
    unsigned long long nTicksInMillisecond = nFreq / 1000;

    return nTicks / nTicksInMillisecond;
}

unsigned long long GetTickMicroseconds(unsigned long long nTicks,unsigned long long nFreq)
{
    unsigned long long nTicksInMicrosecond = nFreq / 1000000;

    return nTicks / nTicksInMicrosecond;
}
于 2013-01-11T13:17:58.420 に答える
0

これをチェックしてください:C ++でシステム時間を取得する方法は?

また、GetTickCountを使用することもできます。これ は、システムが起動してから最大49。7日経過したミリ秒数を取得します。

于 2013-01-10T14:38:13.230 に答える
0

QueryPerformanceFrequency および QueryPerformanceCounter API 関数を使用します。

LARGE_INTEGER freq;
::QueryPerformanceFrequency(&freq);

LARGE_INTEGER start, end;
::QueryPerformanceCounter(&start);
// do some work
::QueryPerformanceCounter(&end);

double const t = double(end.QuadPart - start.QuadPart) / double(freq.QuadPart);

精度を向上させるために、結果から QueryPerformanceCounter の呼び出しにかかる時間を差し引くことができます。

于 2013-01-10T14:38:44.503 に答える
0

Stopwatch クラスは、QueryPerformanceCounter のラッパーです。

uint64_t startTime, endTime;
uint64_t frequency;
QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
QueryPerformanceCounter((LARGE_INTEGER*)&startTime);
//DoStuff
QueryPerformanceCounter((LARGE_INTEGER*)&endTime);
double seconds = (endTime-startTime)/(double) frequency;
于 2013-01-10T14:38:50.680 に答える