web-dev-qa-db-ja.com

C clock()が0を返す理由

私はこのようなものを持っています:

clock_t start, end;
start=clock();

something_else();

end=clock();
printf("\nClock cycles are: %d - %d\n",start,end);

そして、私は常に出力として「クロックサイクルは次のとおりです:0-0」を取得します

なぜこれが起こるのか考えはありますか?

(詳細を説明するために、something_else()関数は、モンゴメリ表現を使用して左から右へのべき乗を実行します。さらに、something_else()関数が実際に無視できないほどの時間を要するかどうかはわかりません。)

これはLinux上にあります。 uname-aの結果は次のとおりです。

Linux snowy.*****.ac.uk 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux

9
eddy ed

clock関数はCPUクロックサイクルを測定しません。

Cは、clock "は、実装の最良の近似値を、プログラムが最初から使用したプロセッサ時間に返します。プログラムの呼び出しにのみ関連する実装定義の時代のことです。」

2つの連続するclock呼び出しの間に、プログラムがclock関数の1つの単一性よりも短い時間で済む場合、0を取得できます。

POSIX clockは、CLOCKS_PER_SECとのユニティを1000000として定義します(ユニティは1マイクロ秒になります)。

http://pubs.opengroup.org/onlinepubs/009604499/functions/clock.html

X86/x64でクロックサイクルを測定するには、インラインアセンブリを使用して、CPUタイムスタンプカウンターレジスタrdtscのクロックカウントを取得できます。

7
ouah

その理由はあなたのsomething_else()clock()の精度を超えるほどの時間を消費しないからだと思います。その結果、clock()を2回呼び出してみましたが、startendはどちらもゼロですが、その間に時間のかかる作業を行うと、結果は妥当です。

これが私のテストコードスニペットです:

_int main(void) {   
    clock_t start, end;
    start = clock();
    int c;
    for (int i = 0; i < 100; i++) {
        for (int j = 0; j < (1<<30); j++) {
            c++;
        }
    }
    end = clock();
    printf("start = %d, end = %d\n", start, end);
    return 0;
}
_

そして、私のコンピューターでの結果は次のとおりです。

_start = 0, end = 27700000
_

また、2つのヒント:

  1. テストするとき、コンパイラの最適化を使用しないでくださいsomething_else()は時間がかかると思うかもしれませんが、コンパイラーはそれらの操作(特にループ)を無意味だと考えるので無視するかもしれません。
  2. プラットフォームでsizeof(clock_t)を使用して、_clock_t_のサイズを確認します。
6
Jinghao Shi

さて、something_else()にかかる時間は必要ですか?これを試して:

#include <sys/time.h>
#include <stdio.h>  
#include <unistd.h>
int main(void) {
    struct timeval start, end;
    long mtime, secs, usecs;    

    gettimeofday(&start, NULL);
    something_else();
    gettimeofday(&end, NULL);
    secs  = end.tv_sec  - start.tv_sec;
    usecs = end.tv_usec - start.tv_usec;
    mtime = ((secs) * 1000 + usecs/1000.0) + 0.5;
    printf("Elapsed time: %ld millisecs\n", mtime);
    return 0;
}
5
Enrique Marcos

_CLOCKS_PER_SEC_の_time.h/clock.h_の値を確認してください。たとえば、私のシステムでは(Windows7のDevCpp)は単なる_1000_です。私のプログラムに関する限り、毎秒1000ティックがあります。 _something_else_はマイクロ秒単位で実行されます。したがって、clock()は、関数呼び出しの前後の両方でゼロを返します。

私のシステムでは、あなたの_something_else_をこのような時間のかかるルーチンに置き換えると

_for (unsigned i=0xFFFFFFFF;i--;);

start=clock();

for (unsigned i=0xFFFFFFFF;i--;);

end=clock();
_

私は得る

クロックサイクルは次のとおりです:10236-20593

Linuxボックスの1つで、_bits/time.h_に次のものがあります。

_/* ISO/IEC 9899:1990 7.12.1: <time.h>
   The macro `CLOCKS_PER_SEC' is the number per second of the value
   returned by the `clock' function. */
/* CAE XSH, Issue 4, Version 2: <time.h>
   The value of CLOCKS_PER_SEC is required to be 1 million on all
   XSI-conformant systems. */
#  define CLOCKS_PER_SEC  1000000l
_

したがって、clock()の戻り値を分析する前に、これを考慮してください。

2
Pavan Manjunath

Clock()を使用して時間を測定する正しい方法は次のとおりです。

printf("\nTime elapsed: %.2f\n",1.0*(end-start)/CLOCKS_PER_SEC);

これは、clock_tがint、またはその他のタイプであることが保証されていないためです。

2
Guido

以下の小さなプログラムを使用して、実時間とCPU時間を調査しました。

私のテストシステムでは、これは印刷されます

CLOCKS_PER_SEC 1000000

CPU time usage resolutionは0.010000 secondsのようです

gettimeofdayが9634 uSによって変更された場合、CPU時間が0.010000によって変更された場合

gettimeofdayの解像度は1米ドルのようです

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <ctime>


int main(int argc, char** argv) {

    struct  timeval now; // wall clock times
    struct  timeval later;

    clock_t tNow = clock(); // clock measures CPU time of this Linux thread
    gettimeofday(&now, NULL); // wall clock time when CPU time first read

    clock_t tLater = tNow;
    while (tNow == tLater)
           tLater = clock(); // consume CPU time

    gettimeofday(&later, NULL); // wall clock time when CPU time has ticked

    printf("CLOCKS_PER_SEC %ld\n",CLOCKS_PER_SEC);

    double cpuRes = (double)(tLater - tNow)/CLOCKS_PER_SEC;

    printf("CPU time usage resolution looks to be %f seconds\n", cpuRes);

    unsigned long long nowUs = ((unsigned long long)now.tv_sec) * 1000000ULL;
    nowUs += (unsigned long long)now.tv_usec;

    unsigned long long laterUs = ((unsigned long long)later.tv_sec) * 1000000ULL;
    laterUs += (unsigned long long)later.tv_usec;

    printf("gettimeofday changed by %d uS when CPU time changed by %f seconds\n", (int)(laterUs - nowUs), cpuRes);

    // now measure resolution of gettimeofday

    gettimeofday(&now, NULL);
    later = now;

    while ((now.tv_sec  == later.tv_sec) && (now.tv_usec == later.tv_usec))
            gettimeofday(&later, NULL);

    nowUs = ((unsigned long long)now.tv_sec) * 1000000ULL;
    nowUs += (unsigned long long)now.tv_usec;

    laterUs = ((unsigned long long)later.tv_sec) * 1000000ULL;
    laterUs += (unsigned long long)later.tv_usec;

    printf("gettimeofday resolution looks to be %d us\n", (int)(laterUs - nowUs));

}
1
user3782374