web-dev-qa-db-ja.com

Cプログラムの実行時間

複数のプロセッサで並列実行することを目的としたCプログラムがあります。実行時間を記録できる必要があります(1秒から数分まで)。私は答えを探しましたが、すべてがclock()関数を使用することを提案しているようです。それは、プログラムがとったクロック数をClocks_per_second値で割って計算することを含みます。

Clocks_per_second値の計算方法がわかりませんか?

Javaでは、実行の前後にミリ秒単位で現在の時間を取得します。

Cにも同様のことがありますか?私は一見したことがありますが、2番目の解像度よりも優れた方法を見つけることができないようです。

また、プロファイラーがオプションになることも承知していますが、自分でタイマーを実装することを検討しています。

ありがとう

190
Roger

CLOCKS_PER_SEC<time.h>で宣言されている定数です。 Cアプリケーション内のタスクによって使用されるCPU時間を取得するには、次のようにします。

clock_t begin = clock();

/* here, do your time-consuming job */

clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;

これは時間を浮動小数点型として返すことに注意してください。これは1秒よりも正確です(例:4.52秒)。精度はアーキテクチャによって異なります。最近のシステムでは10ms以下になりますが、古いWindowsマシンでは(Win98時代から)60msに近くなりました。

clock()は標準Cです。それは "どこでも"動作します。 Unixライクなシステムではgetrusage()のようなシステム特有の関数があります。

JavaのSystem.currentTimeMillis()は同じことを測っていません。これは「掛け時計」です。プログラムの実行に要した時間を測定するのに役立ちますが、使用されたCPU時間はわかりません。マルチタスクシステム(つまり、それらすべて)では、これらは大きく異なる可能性があります。

302
Thomas Pornin

実行にUnixシェルを使用している場合は、timeコマンドを使用できます。

している

$ time ./a.out

実行可能ファイルとしてa.outを仮定すると、これを実行するのにかかる時間をuに与えるでしょう。

106
S..K

あなたは機能的にこれが欲しい:

#include <sys/time.h>

struct timeval  tv1, tv2;
gettimeofday(&tv1, NULL);
/* stuff to do! */
gettimeofday(&tv2, NULL);

printf ("Total time = %f seconds\n",
         (double) (tv2.tv_usec - tv1.tv_usec) / 1000000 +
         (double) (tv2.tv_sec - tv1.tv_sec));

これは秒単位ではなく、マイクロ秒単位で測定されることに注意してください。

56
Wes Hardaker

普通のバニラCでは:

#include <time.h>
#include <stdio.h>

int main()
{
    clock_t tic = clock();

    my_expensive_function_which_can_spawn_threads();

    clock_t toc = clock();

    printf("Elapsed: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);

    return 0;
}
54
Alexandre C.

ほとんどの簡単なプログラムはミリ秒単位の計算時間を持っています。だから、私はあなたがこれが便利だと思うでしょう。

#include <time.h>
#include <stdio.h>

int main(){
    clock_t start = clock();
    // Execuatable code
    clock_t stop = clock();
    double elapsed = (double)(stop - start) * 1000.0 / CLOCKS_PER_SEC;
    printf("Time elapsed in ms: %f", elapsed);
}

あなたがプログラム全体の実行時間を計算したい、そしてあなたがUnixシステムの上にいるなら、このような time コマンドを使ってあなたのプログラムを実行してくださいtime ./a.out

12
adimoh

CLOCKS_PER_SECからclock()そしてtime.hを提案する答えがたくさんありました。これは私の/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

#  if !defined __STRICT_ANSI__ && !defined __USE_XOPEN2K
/* Even though CLOCKS_PER_SEC has such a strange value CLK_TCK
presents the real value for clock ticks per second for the system.  */
#   include <bits/types.h>
extern long int __sysconf (int);
#   define CLK_TCK ((__clock_t) __sysconf (2))  /* 2 is _SC_CLK_TCK */
#  endif

したがって、CLOCKS_PER_SECは、コンパイルに使用するオプションによっては1000000と定義されることがあります。したがって、これは良い解決策とは言えません。

9
Stephen

マクロとしてのThomas Porninの答え:

#define TICK(X) clock_t X = clock()
#define TOCK(X) printf("time %s: %g sec.\n", (#X), (double)(clock() - (X)) / CLOCKS_PER_SEC)

このように使用してください。

TICK(TIME_A);
functionA();
TOCK(TIME_A);

TICK(TIME_B);
functionB();
TOCK(TIME_B);

出力:

time TIME_A: 0.001652 sec.
time TIME_B: 0.004028 sec.
7
hklel

プログラムの実行に要した時間の測定は、その時点でのマシンの負荷に大きく依存することを考慮する必要があります。

Cで現在時刻を取得する方法はさまざまな方法で達成できることを知っているので、もっと簡単な方法があります。

#include <time.h>

#define CPU_TIME (getrusage(RUSAGE_SELF,&ruse), ruse.ru_utime.tv_sec + \
  ruse.ru_stime.tv_sec + 1e-6 * \
  (ruse.ru_utime.tv_usec + ruse.ru_stime.tv_usec))

int main(void) {
    time_t start, end;
    double first, second;

    // Save user and CPU start time
    time(&start);
    first = CPU_TIME;

    // Perform operations
    ...

    // Save end time
    time(&end);
    second = CPU_TIME;

    printf("cpu  : %.2f secs\n", second - first); 
    printf("user : %d secs\n", (int)(end - start));
}

それが役に立てば幸い。

よろしく!

4
redent84

(システム管理者がシステム時刻を変更した場合、またはタイムゾーンの冬時間と夏時間が異なる場合は、ここでのすべての回答が欠けています。したがって...)

Linuxの場合:clock_gettime(CLOCK_MONOTONIC_RAW, &time_variable);システム管理者が時間を変更しても、夏時間とは異なる冬時間の国に住んでいても影響はありません。

#include <stdio.h>
#include <time.h>

#include <unistd.h> /* for sleep() */

int main() {
    struct timespec begin, end;
    clock_gettime(CLOCK_MONOTONIC_RAW, &begin);

    sleep(1);      // waste some time

    clock_gettime(CLOCK_MONOTONIC_RAW, &end);

    printf ("Total time = %f seconds\n",
            (end.tv_nsec - begin.tv_nsec) / 1000000000.0 +
            (end.tv_sec  - begin.tv_sec));

}

man clock_gettimeは次のように述べています。

CLOCK_MONOTONIC
              Clock  that  cannot  be set and represents monotonic time since some unspecified starting point.  This clock is not affected by discontinuous jumps in the system time
              (e.g., if the system administrator manually changes the clock), but is affected by the incremental adjustments performed by adjtime(3) and NTP.
3
JohnSll

ANSI Cは2次精度時間関数のみを指定します。ただし、POSIX環境で実行している場合は、UNIXエポック以降に経過した時間をマイクロ秒単位で解決する gettimeofday() 関数を使用できます。

ちなみに、clock()は多くの(全部ではないにしても)システムにうまく実装されておらず正確ではないので、私はお勧めしません。あなたの質問によれば、それは私があなたが測定したいと思うものであるものです。

3
Shinnok

すべての解決策が私のシステムでは機能していません。

私は慣れることができます

#include <time.h>

double difftime(time_t time1, time_t time0);
2
    #include<time.h>
    #include<stdio.h>
    int main(){
clock_t begin=clock();

    int i;
for(i=0;i<100000;i++){
printf("%d",i);

}
clock_t end=clock();
printf("Time taken:%lf",(double)(end-begin)/CLOCKS_PER_SEC);
}

このプログラムは魅力的に機能します。

2

誰もがここで推奨する通常のclock()が、何らかの理由で、画面への描画やファイルの読み取りなどの副作用のない静的コードであっても、実行ごとに大きく異なることがわかりました。 CPUが消費電力モードを変更したり、OSが異なる優先順位を与えたりするなどの理由が考えられます。

そのため、clock()で毎回確実に同じ結果を得る唯一の方法は、測定されたコードをループで複数回(数分間)実行することです。ループ内で実行される副作用なしに、ループの外に移動します。たとえば、各反復にランダム入力を使用します。

十分なサンプルが配列に収集された後、その配列を並べ替え、中央値と呼ばれる中央の要素を取得します。中央値は平均よりも優れています。これは、アンチウイルスがすべてのCPUを占有する、OSが何らかの更新を行うなど、極端な逸脱を排除するためです。

C/C++コードの実行パフォーマンスを測定し、中央値に近い値を平均化する簡単なユーティリティを次に示します。 https://github.com/saniv/gauge

私はまだ、コードを測定するためのより堅牢で高速な方法を探しています。おそらく、OSなしのベアメタルで制御された条件でコードを実行してみることもできますが、実際にはOSが関与するため、非現実的な結果をもたらします。

x86には、実行された実際の命令数を含むこれらのハードウェアパフォーマンスカウンターがありますが、OSヘルプなしでアクセスするのは難しく、解釈が難しく、独自の問題があります( http://archive.gamedev.net/archive /reference/articles/article213.html )。それでも、ボトルネックの性質(データアクセスまたはそのデータの実際の計算)の調査に役立つ可能性があります。

1
SmugLispWeenie

NVidia CUDA( course description )を使用したGPGPUプログラミングの大学コースの一部として、この方法で時間を測定する方法が与えられました。それは以前の投稿で見られた方法を組み合わせており、要件がそれに信頼性を与えるので、私は単にそれを投稿します:

unsigned long int elapsed;
struct timeval t_start, t_end, t_diff;
gettimeofday(&t_start, NULL);

// perform computations ...

gettimeofday(&t_end, NULL);
timeval_subtract(&t_diff, &t_end, &t_start);
elapsed = (t_diff.tv_sec*1e6 + t_diff.tv_usec);
printf("GPU version runs in: %lu microsecs\n", elapsed);

私はあなたが例えばで乗算できると思います1.0 / 1000.0を使用して、ニーズに合った測定単位を取得します。

0
Alexander