• ベストアンサー

メモリアクセス時間の計測方法

7o8の回答

  • 7o8
  • ベストアンサー率55% (5/9)
回答No.6

そーいえば、おもしろいツールを思い出しました。 午後ベンチと言われるものですが、これはベンチの他、アクセスに要した クロック数も確認できます。 因みに私の環境はこーなります。 ======================================= --- GogoWinBench 1.28 [2009/10/18 23:29:03] --- [OS] Windows NT 6.1 (6.1.7100) [CPU] AMD Phenom(tm) II X4 940 Processor * 4 / 3010.2MHz AuthenticAMD AMD Phenom(tm) II X4 940 Processor 1/0/0/15/4/2 FPU TSC MSR CMOV MMX MMXE SSE SSE2 3DN 3DNE HT(4) L1CodeCache 64KB, 2Way L1DataCache 64KB, 2Way, 89732.76MB/s, 3clk L2Cache 512KB, 16Way, 22515.62MB/s, 12clk Memory 4096MB, 9234.48MB/s, 49clk [DLL] GOGO DLL ver. 2.39b for only bench (Feb 28 2002) ======================================= core系、athlon 64以降は大体 IPC限界は2.5程度とらしいので とりあえず、命令クロック数=1÷2.5×命令数、メモリはローカル変数で 扱うのであればキャッシュに全て入る(規模にもよりますが)として 2次キャッシュアクセスクロック数×アクセス回数で計算してみては 如何でしょうか? ------------------------------------------- for(i=0; i<NUM_ITER; i++){ c[i] = a[i] + b[i]; → メモリアクセス3回、命令1回(計算) } → メモリアクセス2回、命令3回(計算、判断、分岐) ------------------------------------------- アセンブリコード見ていないので、適当なんですが、上記のような アクセスに分類されるとすれば、1ループで起こるメモリアクセスは5回、 命令は4回、でそれぞれ必要なクロック数は以下のようになるのでは ないでしょうか? メモリ(キャッシュ)アクセス時間:5×14=70clk 命令実行時間         :4÷2.5=1.6clk 命令:メモリ(キャッシュ)アクセス時間=1:43.75 # L1データキャッシュは3clkなのでもっと速いんですが、64kBの2wayってことは # 32kB×2ってことで、そこにユーザプログラムがのっかることってないような気がするので # 考えないことにしました。(^^; IPCが2.5っていうのは限界値であって、もっと低いかも? 詳しく乗っているサイトもなかったので2.5をそのまま採用しましたが、 いずれにしろ、メモリアクセスが例えキャッシュに乗っていても それなりにかかるのは見えたかと思います。 尚、ローカル変数であれば、その領域はスタック上に取得されるため、 比較的キャッシュに乗りやすいところであると考えていますが、 allocによる取得の場合は少なくともスタック上とは別のエリア ですので、キャッシュに乗らない可能性があります。 その場合はまぁメモリ応答時間もふまえて計算してみては 如何でしょうか? 尚、キャッシュの応答時間はCPUによって異なるかと思いますので ご自身でも試されてみるといいかと思います。 #intelだと、キャッシュは若干速かったような気もします。

g47040
質問者

お礼

追加アドバイス有難う御座います。これもかなり参考になります。 一応確認なんですが、おっしゃるツールの表示結果で、 >L2Cache 512KB, 16Way, 22515.62MB/s, 12clk とあります、あら、 >メモリ(キャッシュ)アクセス時間:5×14=70clk の部分は、 5×12=60clk の誤りでしょうか? 御指摘頂いたのにこちらから逆指摘するのは失礼な気もしますが、せっかく頂いたアドバイスを今後に役立てたいので、しっかり理解しておきたいのです。 お時間あるときで構いませんのでご回答頂けると幸いです。

関連するQ&A

  • 実行時間の計測(C言語)

    実行時間について教えてください。 実行時間について不可思議な現象が起きたので疑問に思いました。 C言語においてfor文の2億回ループする場合の実行時間を計測し、計測する内容を変えます。 以下のプログラムのように、時間を計測します。 --------------------        ・        ・ gettimeofday(&t0, NULL);  (計測したい処理) gettimeofday(&t1, NULL);        ・        ・ --------------------- (計測したい処理)に以下のようなプログラムを入れ時間を計測しました。 以下、(計測したい処理)  → それにかかった実行時間 <実行結果 書式(計測したい処理) → 計測された時間 > (1)for ( i = 0; i < 2000000000; i++);         →  5.412432 sec (2)for ( i = 0; i < 2000000000; i++, a++);      →  5.401164 sec (3)for ( i = 0; i < 2000000000; i++, a++,a++);   →  9.340447 sec (4)for ( i = 0; i < 2000000000; i++, a++,a++,a++);   →  13.985456 sec この結果を受けての疑問(1) (2)~(4)までは、加算する回数(a++)が2倍、3倍と増えたため、線形的に実行時間が増えるという理屈で納得できるのですが、 (1)~(2)について、加算する回数(a++)が増えているのに、なぜ実行時間が(1)と(2)では変わらないのか。 アセンブラに直すと、確かに加算回数は増えているはずです。 <実行結果 書式(計測したい処理) → 計測された時間 > (5)for ( i = 0; i < 2000000000; i++);           →  5.412432 sec (6)for ( i = 0; i < 2000000000; i++, a++);        →  5.401164 sec (7)for ( i = 0; i < 2000000000; i++, a++,b++);     →  4.019215 sec (8)for ( i = 0; i < 2000000000; i++, a++,b++,c++);   →  4.008310 sec   実行結果を受けての疑問(2) なぜ、(6)~(7)では、加算される回数は増えているにも関わらず、 (5)より実行時間は短くなっているのか。 ((3)と(7)の時間差があることについは、対象となるレジスタが違うため、並行処理をしていると推察できることはわかります。今回は(5)~(8)にかけて、なぜ実行時間が短くなるのかという質問です。) <前提> ・前提として、プログラム内容に間違いはない。 ・バックグラウンドで動いているプログラムの影響は受けていないとします。 (何度も実行して確認しているので常にこのような結果が得られました。) 疑問1、2について、推測できる理由を教えてください。 <環境> ・Windows7 Corei5 上で VMwareによってUbuntuで実行しています。(VMwareのコア数の設定は1) ・メモリはWindowsOS、VMwareによる設定共に2GB <ソース> #include <stdio.h> #include <sys/time.h> // gettimeofday int main() { struct timeval t0, t1; long l; long i; long h; long j; long k; i = 0; h = 0; l = 0; j = 0; k = 0; gettimeofday(&t0, NULL); for ( i = 0; i < 2000000000; i++,l++,h++,j++); /*この部分の加算を変更して計測しています。*/ gettimeofday(&t1, NULL); printf("i = %ld, l = %ld, h=%ld \n",i,l,h); t1.tv_sec -= t0.tv_sec; if (t1.tv_usec < t0.tv_usec) { t1.tv_sec -= 1; t1.tv_usec += 1000000 - t0.tv_usec; } else { t1.tv_usec -= t0.tv_usec; } printf("%d.%06d sec\n", t1.tv_sec, t1.tv_usec); } わかる方、回答を何卒お願いします。 (解答に必要な条件が足りないのでしたら、教えてください。すぐに追記します。)

  • 2次元配列のポインタ

    整数型行2列2の2次元配列の[1][0]は、ポインタでは3になるとおもっているのですが、ちがったでしょうか? 下記のソースでエラーが出ていて困っています。 void main() { int array[2][2] = { { 9, 9 }, { 9, 9 } }; int num=2, j,i; *(array + 3) = 0; for (i = 0; i < num; i++) { for (j = 0; j < num; j++) { printf("%d", array[i][j]); } puts(""); } } 99 09 と表示させたいのですが、どこに間違いがあるのでしょうか?

  • C言語の事で・・・

    C勉強し始めたばかりなんですが気になってるプログラムがあります。 ttp://akabas.net/lib/CTask.aspx?id=105のページのナンバーズっていうゲームなんですがよく分からない部分があります。どなたか解説してもらえませんか? for( turn = 1 ; ; turn++ ){ int num; int test[4]; int kazu = 0; int keta = 0; int i, j; printf( "数を当ててください。\n" ); scanf( "%d", &num ); test[3] = num % 10; test[2] = ( num / 10 ) % 10; test[1] = ( num / 100 ) % 10; test[0] = ( num / 1000 ) % 10; for( i = 0 ; i < 4 ; i++ ){ for( j = 0 ; j < 4 ; j++ ){ if( numbers[i] == test[j] ){ kazu++; if( i == j ) keta++; のとこです。お願いします。

  • 問題: 以下の2つのプログラムを実装し、時間計算量を実験的に評価せよ。

    問題: 以下の2つのプログラムを実装し、時間計算量を実験的に評価せよ。     (1)1から1万までの整数ちをランダムに1千個生成するプログラム     (2)シェルソートプログラム 質問内容   プログラム()をやったんですが、「時間計算量を実験てきに評価せよ」というのは分かりません。 教えてください。 /* ランダムプログラ*/ #include<stdio.h> #include<stdlib.h> #include<time.h> #define N 1000 void main(){ FILE *fp; int i,rnd; fp=fopen("data.dat","w"); srand((int)time(NULL)); for(i=1;i<=N;i++){ rnd = (int)rand()% 10000 + 1; fprintf(fp,"%d\n ", rnd); } fclose(fp); } /* シェルソートプログラム*/ #include <stdio.h> #include <stdlib.h> #define DATA_NUM 1000 void ShellSort(int num[ ], int n) ; void InsSort(int num[ ], int gap, int n); void ShowData(int num[ ], int n); void main(void); /* n 個のデータのシェルソートを行う */ void ShellSort(int num[ ], int n) { int gap; for (gap = n / 2; gap > 0; gap /= 2) InsSort(num, gap, n); } /* n 個のデータの単純挿入ソートを行う */ void InsSort(int num[ ], int gap, int n){ int i, j, temp; for (i = gap; i < n; i ++) { for (j = i - gap; j >= 0; j -= gap) { /* このループで */ if (num[j] <= num[j + gap]) /* j 番目とj + gap 番目と比較 */ break; /* ここにbreak;を挿入。*/ else { temp = num[j]; /* 要素の入れ替え */ num[j] = num[j + gap]; num[j + gap] = temp; ShowData(num,DATA_NUM); /* 途中経過を表示 */ } } } printf("\n"); /* InsSort( ) を抜ける時改行 */ } /* n 個のデータの表示 */ void ShowData(int num[ ], int n) { while (n--) printf("%d ", *num++); printf("\n"); } void main(void) { FILE *fp; int data[DATA_NUM]; int i; fp = fopen("data.dat","r"); if(fp == NULL){ printf("data.dat cannot be opened"); exit(1); } for(i=0;i<DATA_NUM;i++){ if(fscanf(fp,"%d",&data[i])== NULL){ break; } } printf("ソート前\n"); ShowData(data, DATA_NUM); printf("\n"); /* シェルソート */ ShellSort(data, DATA_NUM); printf("\n"); printf("ソート後\n"); ShowData(data,DATA_NUM); printf("\n"); fclose(fp); }

  • 行列の計算について。

    こんにちは。 JAVAで行列の計算をするプログラムを作っていますが、なかなかうまくいきません。 自分で考えたのはfor文を使った物です。行列数を入力するとその数だけの行列を作る、という物なのですが、どうもうまくいきません。 「2」を入力すると、 │1 2││5 6│ │   ││   │ │3 4││7 8│ こんな2行2列の行列の計算をする、というものです。 for (int i =0; i < 2; i++){ for (int j = 0; j<2; j++){ for (int k = 0; k<2; k++){ C[i][j]=C[i][j]+a[i][k]*b[k][j]; } } } 上のようなプログラムを考えました。 JAVAには行列の計算をする専用の関数(クラス?)などあるのでしょうか? また、ソースなど教えていただけると、とても助かります。 CからJAVAに急に移ったので、つまづくことが非常に多いです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • C言語のプログラムのメモリリークに関して

    動的メモリ管理を用いて,キーボードからの入力を行単位で辞書順にソートして出力するプログラムで、メモリリークが有るため解消したいのですが、freeをどのように用いれば良いのかが分かりません。 動的メモリについての理解が不十分であるため、自分なりにfreeを用いてみるとプログラムが途中で止まってしまい、解消することができません。 以下のプログラムは、自分なりにfreeを用いた部分を除けば、ソート後の出力は正しく出力されます。(メモリリークは発生します。) アドバイス、間違いの指摘等していただければと思います。お願いします。 環境は、Windows XP Professional SP3 32bitでVisual C++ 2008 Expressを使用しています。 #include <stdio.h> #include <string.h> #include <crtdbg.h> #include <stdlib.h> #define MAXLINES 20000 // 最大行数 #define LINELENGTH 20 // 1行の最大文字数 /* 標準入力からの入力を,一行づつ動的に確保したメモリに格納し, そのアドレスを文字列へのポインタ配列に保存する. Ctrl+Zで入力を終了する. lines : 文字列へのポインタの配列 numMax : 最大の読み込み行数*/ int ReadLines(char *lines[], int numMax){ int cnt = 0; static char buf[LINELENGTH]; while (cnt < numMax && gets(buf)) { lines[cnt] = malloc(strlen(buf) + 1); if (lines[cnt] == NULL) { printf("Allocation error.\n"); break; } strcpy(lines[cnt], buf); cnt++; } return cnt; } /* ポインタ配列の指す文字列を標準出力に表示 lines : 文字列へのポインタの配列 num : 行数*/ void PrintLines(char *lines[], int num){ int i; for (i = 0;i < num;i++) printf("%s\n", lines[i]); } /* ポインタの配列を,辞書順にソート lines : 文字列へのポインタの配列 num : 行数*/ void Sort(char *lines[], int num){ int i,j; char temp[LINELENGTH]; for(i=0;i<num;i++){ for(j=num-1;j>i;j--){ if(strcmp(lines[j],lines[j-1])<0){ strcpy(temp,lines[j]); strcpy(lines[j],lines[j-1]); strcpy(lines[j-1],temp); } } } } int main(){ int cnt,i; static char *lines[MAXLINES]; cnt = ReadLines(lines, MAXLINES); printf("----- %d lines -----\n", cnt); Sort(lines, cnt); PrintLines(lines, cnt); /*自分なりにfreeを用いた部分*/ for(i=0;i<cnt;i++){ free(lines[i]); } //メモリリーク情報の表示 _CrtDumpMemoryLeaks(); return 0; }

  • 100000未満素数の総数を求めるのに困っているので教えてください。

    100000未満素数の総数を求めるのに困っているので教えてください。     #include<stdio.h> #include<math.h> #define NUM 100000 int main(void){ int prime[NUM+1],i,j,Limit; for(i=2;i<=NUM;i++){ prime[i]=1; } Limit=(int)sqrt(NUM); for(i=2;i<=Limit;i++){ if(prime[i]==1){ for(j=2*i;j<=NUM;j+=i){ prime[j]=0; } } } for ( i=2;i<=NUM;i++) {  if (prime[i]) {    printf("%d\n",i);   } } } これなんですが、実行したらエラーが出てしまうんですがなぜでしょうか?

  • atoi関数の自作

    C言語でatoi関数を自作したのですが、正確な答えが出てきません 以下にソースを貼るのでどの当たりを直したらよいのかご教授願います。 1~9までの文字列を一つずつ配列に格納して変換する事を目的として作っています。 実行すると桁あふれしたような値が出てきてしまいます #include<stdio.h> #include<stdlib.h> int pow_10(int m) { int i,prod=1; for(i=0;i<m;i++){ prod=prod*10; } return prod; } ascii2int(char number[]){ int i,j,n[10],num; if(!strcmp(number,"")){ printf("Null string\n"); exit(1); } i=0; while(n[i]!='\0'){ n[i]=n[i]-48; i++; } num=0; for(j=0;j<i;j++){ num=num+n[j]*pow_10(i-1-j); } return num; } main(){ char su[10]; for(;;){ printf("Enter an integar:"); gets(su); if(!strcmp("x",su)){ break; } printf("%d\n",ascii2int(su)); } }

  • C言語にて、XORの演算時間を取得するには?

    題名の通りです。 C言語で、XOR命令の演算時間を取得しようとしています。演算時間を取得する関数部分は下の通りで、a^=b, b^=aをひたすら繰り返すことで、命令の演算時間を取得する、というものです。この方法を使って、ADD命令については演算時間を取得できました。しかし、XORについては、計測時間がほぼゼロになり、XORが動いていないようです。 その理由は、同じ値をXORすると元に戻るというXORの原理のため、コンパイラの最適化によりfor文内のXOR命令が消えてしまったからだと考えられます。 かといって、t1とt2にvolativeを付けて宣言すれば、最適化によって消去はされませんが、volativeの性質上、メモリアクセスの時間を取得することになってしまいます。 どうすれば、XOR命令のみの演算時間を取得できるでしょうか。 アイディアや指摘がありましたら、どうかご教授下さい。 -------------------------------------------------------------- #define ADD(a, b) a+=b #define XOR(a, b) a^=b /* 10回反復するマクロ */ #define repeat10(S) S S S S S S S S S S /* 各命令の演算時間を計測する関数 */ void operation_test( unsigned int *out, unsigned int p1, unsigned int p2, int its) { /* volatileを付けた宣言だと、t1とt2はメモリに取られるため、目的を達成できない */ unsigned int t1 = p1; unsigned int t2 = p2; /* itsは反復回数 */ for(int i=0; i<its; i++){ /* いずれかの行を選択する。ADDはきちんと演算されているよ */ /* うだが、XORは最適化により消去されてしまっているらしい */ repeat10(ADD(t1, t2); ADD(t2, t1); ) //repeat10(XOR(t1, t2); XOR(t2, t1); ) } out[0]=t1+t2; } --------------------------------------------------------------

  • 最大値と最小値を表示したいのですが・・・

    double numに入っている数字から最大値と最小値を求めたいのですが、このままだと両方とも1.000になってしまうんです・・・ どうやったらちゃんと最大値と最小値が表示されるのでしょうか?? 初心者なものでスイマセンが教えてください!! #include<stdio.h> int main(void) { int i,j; double num[]={4.5,3.1,7.0,9.2,1.0,5.7,9.3,2.3,0.3,1.0}; double max,min; for(i=0; i<10; i++) { for(j=0; j<10; j++) { if(num[i]>num[j]) max=num[i]; } } for(i=0; i<10; i++) { for(j=0; j<10; j++) { if(num[i]<num[j]) min=num[i]; } } printf("最大値は%fです。",max); printf("最小値は%fです。",min); return 0; }