1

getitimer と setitimer を使用して単純な操作を実行するのにかかる時間を取得するために、次の C コードを作成しています。

#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>

#define INTERVAL 1        /* number of milliseconds to go off */

int main() {
    double sum = 0;
    struct itimerval initial, updated;

    initial.it_value.tv_sec     = INTERVAL;
    initial.it_value.tv_usec    = 999999;
    initial.it_interval = initial.it_value;
    memcpy(&(initial.it_interval), &(initial.it_value), sizeof( initial.it_value )); 
    printf("%ld\n", initial.it_value.tv_usec);

    if (setitimer(ITIMER_VIRTUAL, &initial, NULL) == -1) {
        perror("error calling setitimer()");
        exit(1);
    }

    for (unsigned int i; i < 100; i++) 
        sum += 1./i;

    if (getitimer(ITIMER_REAL, &updated) == -1) {
        perror("error calling getitimer()");
        exit(1);
    }

    printf("Time started = %ld\n; Time ended = %ld\n: Time taken = %ld\n",
           initial.it_value.tv_usec, updated.it_value.tv_usec,
           initial.it_value.tv_usec - updated.it_value.tv_usec);
    return 0;
}

私はコンパイルしました:

$ gcc -o timer -std=c99 -Wall -pedantic getitimer.c -lrt -03

ただし、私の答えは常に 999999 です (100 を上げ下げしました)。

 ./timer 
999999
Time started = 999999
; Time endd = 0
: Time taken = 999999

私のエラーは何ですか?また、このようなプログラムを使用して得られる最高の精度はどれくらいですか?

どうもありがとう!

4

3 に答える 3

1

私が見る主なことは、除算が整数除算を使用していることです。そう:

initial.it_value.tv_sec     = INTERVAL/1000000;

tv.sec に 0 を置きます

initial.it_value.tv_usec    = (INTERVAL/1000000) * 1000000;

tv_usec に 0 を置きます

initial.it_interval = initial.it_value;

一般に、複数フィールドの構造体を割り当てるときmemcpy()は、直接代入ではなく を使用します。(直接代入は初期化には機能しますが、代入には機能しません。)

したがって、投稿されたコードは「間隔」を0に設定します

もちろん、結果の値は0です

これは、man ページの setitimer() および getitimer() の重要なステートメントです。

「タイマーは it_value からゼロに減分し、シグナルを生成し、it_interval にリセットします。ゼロに設定されたタイマー (it_value がゼロであるか、タイマーが期限切れになり、it_interval がゼロである) は停止します。」

提案:以下の編集

initial.it_value.tv_set = INTERVAL;
initial.it_value.tv_usec = 0;

memcpy( &(initial.it_interval), &(initial.it_value), sizeof( initial.it_value ) );

...
于 2016-02-27T06:08:36.993 に答える
0

最新のコードの主な問題は、への呼び出しがへの呼び出しとgetitimer()は異なるタイマーを参照していることです。setitime()

ただし、次のコードを使用すると簡単に使用できます

#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
//#include <limits.h>
//#include <string.h>

// do not place comments on same line as #define statement
// always surround numeric values with parens to avoid 'text replacement' errors
// wrong comment:  number of milliseconds to go off

// number of seconds in interval
#define INTERVAL (1)

// number of usec in interval
#define MICRO_INTERVAL (999999)

int main() {
    //double sum = 0;
    struct itimerval initial;
    struct itimerval updated;

    initial.it_value.tv_sec     = INTERVAL;
    initial.it_value.tv_usec    = MICRO_INTERVAL;
    initial.it_interval.tv_sec  = INTERVAL;
    initial.it_interval.tv_usec = MICRO_INTERVAL;

    // remove this line: initial.it_interval = initial.it_value;
    // remove this line: memcpy(&(initial.it_interval), &(initial.it_value), sizeof( initial.it_value ));
    //printf("%ld\n", initial.it_value.tv_usec);

    printf( "Time value: %ld.%ld\n", initial.it_value.tv_sec, initial.it_value.tv_usec );
    printf( "Time interval: %ld.%ld\n", initial.it_interval.tv_sec, initial.it_interval.tv_usec );

    if (setitimer(ITIMER_VIRTUAL, &initial, &updated) == -1)
    {
        perror("error calling setitimer()");
        exit(1);
    }

    //for (unsigned int i=0; i < 10; i++)  // must initialize the 'i' variable
    //    sum += 1./i;

    // the 'which' parameter should be 'ITIMER_VIRTUAL'
    //     as that is what was started in the call to setitimer()
    //if (getitimer(ITIMER_REAL, &updated) == -1)
    //{
    //    perror("error calling getitimer()");
    //    exit(1);
    //}

    if (setitimer(ITIMER_VIRTUAL, &initial, &updated) == -1)
    {
        perror("error calling setitimer()");
        exit(1);
    }

    printf( "end interval counter: %ld.%ld\n", updated.it_interval.tv_sec, updated.it_interval.tv_usec );
    printf( "end value counter: %ld.%ld\n", updated.it_value.tv_sec, updated.it_value.tv_usec );

    //printf("Time started = %ld\n; Time ended = %ld\n: Time taken = %ld\n",
    //       initial.it_value.tv_usec, updated.it_value.tv_usec,
    //       initial.it_value.tv_usec - updated.it_value.tv_usec);
    return 0;
}

// accuracy is +/-1 microsecond, not millisecond

結果の出力は、2 つの呼び出しの間に何も行われていない場合でも、次のようになりますsetitimer()

Time value: 1.999999
Time interval: 1.999999
end interval counter: 1.999999
end value counter: 2.3999
于 2016-02-27T23:24:29.873 に答える