0

次のコードの CPU 時間を測定しようとしています - struct timespec time1, time2, temp_time;

          clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);

          long diff = 0;

          for(int y=0; y<n; y++) {

                for(int x=0; x<n; x++) {

                float v = 0.0f;

                 for(int i=0; i<n; i++)

                     v += a[y * n + i] * b[i * n + x];

                       c[y * n + x] = v;

                   }

            }
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);

        temp_time.tv_sec = time2.tv_sec - time1.tv_sec;

        temp_time.tv_nsec = time2.tv_nsec - time1.tv_nsec;

        diff = temp_time.tv_sec * 1000000000 + temp_time.tv_nsec; 

       printf("finished calculations using CPU in %ld ms \n", (double) diff/1000000); 

しかし、n の値を大きくすると、時間の値は負になります。コードは n = 500 の場合は正しい値を出力しますが、n = 700 の場合は負の値を出力します。

完全なコード構造は次のとおりです-

void run(float A[], float B[], float C[], int nelements){
    struct timespec time1, time2, temp_time;

          clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);

          long diff = 0;

          for(int y=0; y<nelements; y++) {

                for(int x=0; x<nelements; x++) {

                float v = 0.0f;

                 for(int i=0; i<nelements; i++)

                     v += A[y * nelements + i] * B[i * nelements + x];

                       C[y * nelements + x] = v;

                   }

            }
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);

        temp_time.tv_sec = time2.tv_sec - time1.tv_sec;

        temp_time.tv_nsec = time2.tv_nsec - time1.tv_nsec;

        diff = temp_time.tv_sec * 1000000000 + temp_time.tv_nsec; 

       printf("finished calculations using CPU in %ld ms \n"(double) diff/1000000); 
}

この関数 abovr は、次のように異なるファイルから呼び出されます。

SIZE = 500;

a = (float*)malloc(SIZE * SIZE * sizeof(float));

b = (float*)malloc(SIZE * SIZE * sizeof(float));

c = (float*)malloc(SIZE * SIZE * sizeof(float));

//initialize a &b
run(&a[SIZE],&b[SIZE],&c[SIZE],SIZE);
4

4 に答える 4

2

unsigned longオーバーフローの使用またはより良いようdoubleに見えますdiff

于 2012-05-10T05:24:02.590 に答える
0

考えられる問題の原因の1つは、printf形式が長符号付き整数値(%ld)用であるが、パラメーターがdouble型であるということです。この問題を解決するには、フォーマット文字列をに変更%ldする必要があります。%lf

于 2012-05-10T06:04:07.797 に答える
0

あなたの印刷物の声明を見てください:

printf("finished calculations using CPU in %ld ms \n", (double) diff/1000000);

渡す2番目のパラメーターはdoubleですが、この浮動小数点値をlong(%ld)として出力しています。それがあなたの問題の半分だと思います。

これにより、より良い結果が得られる可能性があります。

printf("finished calculations using CPU in %f ms \n", diff/1000000.0);

また、keetyにも同意します。おそらく、符号なしタイプを使用する必要があります。または、ナノ秒ではなくミリ秒単位のままにすることで、オーバーフローの問題を完全に回避できます。これが、64ビットの符号なし整数を使用してミリ秒の領域にとどまる理由です。

unsigned long long diffMilliseconds;

diffMilliseconds = (time2.tv_sec * 1000LL + time2.tv_nsec/1000000) - (time1.tv_sec * 1000LL + time1.tv_nsec/1000000);

printf("finished calculations using CPU in %llu ms \n", diffMilliseconds);
于 2012-05-10T06:05:48.440 に答える
0

明らかな理由から、「tv_nsec」フィールドは 10^9 (1000000000) を超えてはなりません。

if (time1.tv_nsec < time2.tv_nsec)
{
    int adj = (time2.tv_nsec - time1.tv_nsec) / (1000000000) + 1;

    time2.tv_nsec -= (1000000000) * adj;
    time2.tv_sec += adj;
}

if (time1.tv_nsec - time2.tv_nsec > (1000000000))
{
    int adj = (time1.tv_nsec - time2.tv_nsec) / (1000000000);

    time2.tv_nsec += (1000000000) * adj;
    time2.tv_sec -= adj;
}

temp_time.tv_sec = time1.tv_sec - time2.tv_sec;
temp_time.tv_nsec = time1.tv_nsec - time2.tv_nsec;

diff = temp_time.tv_sec * (1000000000) + temp_time.tv_nsec;

このコードは、「tv_sec」フィールドの符号について何の仮定もしていないため、単純化できます。ほとんどの Linux sys ヘッダー (および glibc?) は、この種の timespec 演算を正しく処理するためのマクロを提供していますね。

于 2012-05-10T05:52:50.457 に答える