4
#include <iostream>
#include <conio.h>
#include <ctime>



using namespace std;

double diffclock(clock_t clock1,clock_t clock2)
{
    double diffticks=clock1-clock2;
    double diffms=(diffticks)/(CLOCKS_PER_SEC/1000);
    return diffms;
}
int main()
{
    clock_t start = clock();
    for(int i=0;;i++)
    {

    if(i==10000)break;
    }
    clock_t end = clock();

    cout << diffclock(start,end)<<endl;

    getch();
return 0;
}

だから私の問題はそれが私に0を返すということです、まあ、私は私のプログラムがどれくらいの時間を動作するかをチェックしたいです...私はインターネット上でたくさんのがらくたを見つけましたほとんどそれは0を得るのと同じポイントになります開始と終了が同じであるため

この問題はC++の記憶に行きます:<

4

5 に答える 5

12

ここにはいくつかの問題があります。1つ目は、機能に移行するときに、明らかに開始時刻と停止時刻を切り替えたことですdiffclock()。2番目の問題は最適化です。最適化が有効になっている適度にスマートなコンパイラーは、副作用がないため、ループ全体を単純に破棄します。しかし、上記の問題を修正しても、プログラムはおそらく0を出力します。1秒あたり数十億の操作を実行することを想像しようとすると、最新のCPUで採用されている高度なアウトオブオーダー実行、予測、およびその他のテクノロジーを大量に投入します。ループを最適化します。ただし、そうでない場合でも、実行時間を長くするには、10Kを超える反復が必要になります。clock()何かを反映させるには、おそらくプログラムを1、2秒実行する必要があります。

しかし、最も重要な問題はclock()それ自体です。この機能は、パフォーマンス測定のどの時点にも適していません。これにより、プログラムで使用されるプロセッサ時間の概算が得られます。特定の実装で使用される可能性のある近似方法のあいまいな性質は別として(標準では特定のものを必要としないため)、POSIX標準も実際の解像度とは無関係である必要CLOCKS_PER_SECがあります。1000000言い換えると、クロックがどれほど正確であるかは関係ありません。CPUが実行されている周波数は関係ありません。簡単に言えば、これはまったく役に立たない数値であるため、まったく役に立たない関数です。それがまだ存在する唯一の理由は、おそらく歴史的な理由によるものです。なので、使わないでください。

あなたが探しているものを達成するために、人々はそれを読むために使用される対応するCPU命令の名前で「RDTSC」としても知られているCPUタイムスタンプを読んでいました。ただし、最近では、これもほとんど役に立たない理由があります。

  1. 最新のオペレーティングシステムでは、プログラムを1つのCPUから別のCPUに簡単に移行できます。別のCPUで1秒間実行した後、別のCPUでタイムスタンプを読み取ることはあまり意味がないことを想像できます。最新のIntelCPUでのみ、カウンターはCPUコア間で同期されます。全体として、これを行うことはまだ可能ですが、多くの特別な注意を払う必要があります(つまり、プロセスへのアフィニティを一度設定できるなど)。
  2. プログラムのCPU命令を測定しても、実際に使用されている時間を正確に把握できないことがよくあります。これは、実際のプログラムでは、プロセスに代わってOSカーネルによって作業が実行されるシステムコールが発生する可能性があるためです。その場合、その時間は含まれません。
  3. また、OSがプロセスの実行を長時間中断することもあります。そして、実行するのにほんの数命令しかかかりませんでしたが、ユーザーにとっては1秒のように見えました。したがって、このようなパフォーマンス測定は役に立たない場合があります。

じゃあ何をすればいいの?

プロファイリングに関しては、のようなツールをperf使用する必要があります。これは、CPUクロックの数、キャッシュミス、取得された分岐、欠落した分岐、プロセスが1つのCPUから別のCPUに移動された回数などを追跡できます。ツールとして使用することも、アプリケーションに埋め込むこともできます(PAPIなど)。

そして、質問が実際に費やされた時間についてである場合、人々は壁掛け時計を使用します。好ましくは、高精度のものであり、これもまたNTP調整(単調)の対象ではない。これは、何が起こっていても、正確にどれだけの時間が経過したかを示しています。その目的のためclock_gettime()に使用することができます。これは、SUSv2、POSIX.1-2001標準の一部です。getch()ターミナルを開いたままにするためにあなたを使用することを考えると、私はあなたがWindowsを使用していると思います。残念ながら、そこにはありませんclock_gettime()。最も近いのはパフォーマンスカウンターAPIです。

BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);

ポータブルソリューションの場合、最善の策はにありstd::chrono::high_resolution_clock()ます。これはC++11で導入されましたが、ほとんどの産業用グレードのコンパイラ(GCC、Clang、MSVC)でサポートされています。

以下はその使用例です。私のCPUはミリ秒よりも整数の10000増分を実行することがわかっているので、マイクロ秒に変更したことに注意してください。volatileまた、コンパイラーがカウンターを最適化しないことを期待して、カウンターを宣言しました。

#include <ctime>
#include <chrono>
#include <iostream>

int main()
{
    volatile int i = 0; // "volatile" is to ask compiler not to optimize the loop away.
    auto start = std::chrono::steady_clock::now();
    while (i < 10000) {
        ++i;
    }
    auto end = std::chrono::steady_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    std::cout << "It took me " << elapsed.count() << " microseconds." << std::endl;
}

コンパイルして実行すると、次のように出力されます。

$ g++ -std=c++11 -Wall -o test ./test.cpp && ./test
It took me 23 microseconds.

それが役に立てば幸い。幸運を!

于 2013-03-05T23:09:03.880 に答える
5

一見すると、小さい値から大きい値を引いているように見えます。あなたが呼ぶ:

diffclock( start, end );

しかし、diffclockは次のように定義されます。

    double diffclock( clock_t clock1, clock_t clock2 ) {

        double diffticks = clock1 - clock2;
        double diffms    = diffticks / ( CLOCKS_PER_SEC / 1000 );

        return diffms;
    }

それとは別に、それはあなたが単位を変換している方法と関係があるかもしれません。ミリ秒に変換するための1000の使用は、このページでは異なります。

http://en.cppreference.com/w/cpp/chrono/c/clock

于 2013-03-05T22:31:50.827 に答える
3

問題は、ループが短すぎることのようです。私は自分のシステムでそれを試しました、そしてそれは0ティックを与えました。diffticksが何であるかを確認し、0でした。ループサイズを100000000に増やすと、顕著なタイムラグが発生し、出力として-290を取得しました(バグ-diffticksはclock2-clock1である必要があるため、290を取得する必要があります-290ではありません)。部門で「1000」を「100.0」に変更してみましたが、うまくいきませんでした。

最適化を使用してコンパイルするとループが削除されるため、ループを使用しないか、ループを「何かを実行」する必要があります。たとえば、ループ本体のループカウンター以外のカウンターをインクリメントします。少なくともそれはGCCが行うことです。

于 2013-03-05T22:31:38.573 に答える
2

注:これはc++11以降で使用できます。

std::chronoライブラリを使用できます。std::chronoには2つの異なるオブジェクトがあります。(時点期間)。タイムポイントは、ある時点と期間を表します。これは、この用語が間隔または期間を表すことはすでにわかっているためです。このc++ライブラリを使用すると、2つの時点を減算して、間隔内で経過した時間を取得できます。したがって、開始点と停止点を設定できます。関数を使用して、それらを適切な単位に変換することもできます。

high_resolution_clock(このライブラリが提供する3つのクロックの1つ)を使用した例:

#include <chrono> 
using namespace std::chrono;

//関数を実行する前

auto start = high_resolution_clock::now();

//関数を呼び出した後

auto stop = high_resolution_clock::now();

停止および開始の時点を減算し、duration_cast()関数を使用して必要な単位にキャストします。事前定義された単位は、ナノ秒、マイクロ秒、ミリ秒、秒、分、および時間です。

auto duration = duration_cast<microseconds>(stop - start);
cout << duration.count() << endl;
于 2020-08-19T16:39:34.230 に答える
1

まず第一に、あなたは終わりを引くべきです-その逆ではなく始めてください。
ドキュメントによると、値が利用できない場合、clock()は-1を返します。それを確認しましたか?プログラムをコンパイルするときに、どの最適化レベルを使用しますか?最適化が有効になっている場合、コンパイラはループを効果的に完全に排除できます。

于 2013-03-05T22:26:34.477 に答える