C言語関係掲示板

過去ログ

No645 実行速度重視のプログラミング

[戻る] [ホームページ]
No.6930

実行速度重視のプログラミング
投稿者---もへもへ(2003/05/30 10:25:29)


はじめまして
いま,実行速度重視のプログラミングをしてます.以下の不可解な問題に出くわして大変困っています.以下のソースは,配列w[i]にiを1づつインクリメント(i+=1;)しながら値を入れていくだけの単純なプログラムです.このインクリメント数を2にすると(i+=1;からi+=2;に変更),と途端に実行速度が10倍以上遅くなります.開発環境はWindows2000, VC++6.0(SP5)でコンパイラオプションはデフォルトに,スタックを増やすのとPenPRO用にした(/STACK:64000000 /G6)のみです.3日間悩んでます.どうかよろしく御願いします.

#include <stdio.h>
#include <time.h>
#define nDim 100*100*50

main(void)
{
  int i, k;
  double duration, w[nDim*2];
  clock_t start, finish;

  for(i=0;i<nDim*2;i++) w[i]=0.0;
  start = clock();
  for(k=0;k<400;k++){
    i=0;
    do{
      w[i] = 1.0;
      i+=1;
    }while(i<nDim);
  }
  finish = clock();
  duration = (double)(finish-start)/CLOCKS_PER_SEC;
  fprintf(stderr, "\nduration: %2.3fsec\n",duration);
}



No.6933

Re:実行速度重視のプログラミング
投稿者---もぐりん(2003/05/30 12:10:26)


こんにちは。

私の環境(WinXP Home(SP1), VC++6(SP5),ThinkPad390X
CPU:モバイルセレロン500MHz,Memory:190MB)で、提示されたソース
をコンパイルして実行してみましたが、i+=1;の場合は、7.020sec、
i+=2;の場合は、6.990secとなりましたがどうでしょうか?


No.6935

Re:実行速度重視のプログラミング
投稿者---もへもへ(2003/05/30 13:08:00)


もぐりんさん,ありがとうございます.

質問で一箇所ミスがありました.コンパイルオプションで"/O2"の最適化オプションもつけてコンパイルしていました.結局コンパイルオプションは,/G6 /O2 /STACK:64000000です./O2オプションをはずすと,どちらの場合(i+=1とi+=2)も実行速度は,もぐりんさんの様にほぼ同じになりました.ということは,/O2コンパイルオプションって内部でなにをやっているか知らなくてはいけないということでしょうか??


No.6937

Re:実行速度重視のプログラミング
投稿者---しんちー(2003/05/30 13:47:38)


> ということは,/O2コンパイルオプションって内部でなにをやっているか知らなくてはいけないということでしょうか??

コンパイル全部を行わないで、アセンブラを出力するオプションがあると思うので、それでどういうアセンブラソースになるか見てみては。


No.6939

Re:実行速度重視のプログラミング
投稿者---もへもへ(2003/05/30 15:29:13)


VC++6の環境で,debugモードでアセンブラコードも見てみましたが,
i+=1; ---> add eax, 1
i+=2; ---> add eax, 2
(レジスタeaxには変数iのスタックポインタから読んだ値が入っている)となっています.その他の箇所はまったく同じでした.プログラムサイズも全く同じです.



No.6966

Re:実行速度重視のプログラミング
投稿者---すがり(2003/05/31 22:33:29)


>VC++6の環境で,debugモードでアセンブラコードも見てみましたが,

debugモードで10倍以上変わるんですか?

No.6969

Re:実行速度重視のプログラミング
投稿者---hu(2003/05/31 23:23:01)


再現テスト(VC6,Win2000、/G6 /O2オプション)やってみました。
マシンはAthron XP 1800+です。
・debug
 i+=1: 3.94 秒
 i+=2: 3.07 秒
・release
 i+=1: 0.00 秒
 i+=2: 2.53 秒
debugモードの結果は妥当なところでしょうか。

で、releaseモードでの状況を調べるために、ファイルリスティングを設定して
アセンブラコードと対応するソースコードを出力させてみました。
結論だけ言うと、i+=1の場合は、配列をいじくるコードは全く出ていません。
おそらく、配列の全要素に均一な処理しかない上に、その後に配列を参照する
こともないため、最適化で完全に消去されたのでしょう。

というわけで、試しにソースの最後に
printf("%f", w[100]);
と、配列を参照するコードを追加したところ、3.59秒という結果になり、アセンブラ
でも配列を埋めるコードが出力されてました。

No.6993

Re:実行速度重視のプログラミング
投稿者---もへもへ(2003/06/02 09:58:18)


huさん,検証ありがとうございました.
/O2オプションって賢いですね.参照していないときには,まったく配列処理していないなんて.ちなみにintel complier7.0(評価版)でも,同様のテストをやってみたところ,この場合はi+=1, i+=2とも実行速度は同じ(早い方)でした.ということは,VC6++よりIntelCompiler7.0のほうがちょっと賢い?

あと,huさんのやっていたファイルリスティンングってどうやってやるのでしょうか.もしよかったら教えてください.



No.6940

Re:実行速度重視のプログラミング
投稿者---ちぇっこり(2003/05/30 15:30:50)


>>開発環境はWindows2000, VC++6.0(SP5)でコンパイラオプションは
>>デフォルトに,スタックを増やすのとPenPRO用にした
>>/STACK:64000000 /G6)のみです。

この環境を再現する事は、ちょっと出来ないんですが・・
   #define nDim 100*100*50
を、128*128*48 のようにするってのは、駄目でしたっけ?
すみません。あやふやな答えで・・・

No.6941

Re:実行速度重視のプログラミング
投稿者---もへもへ(2003/05/30 15:49:16)


nDim 128*128*48もやってみましたが,やはり2つのプログラムの実行速度には依然として10倍以上の大きな差があります.現実的なプログラムを考えると提示したプログラムでは単に配列に値を入れるのみで,結果を表示するとかのアウトプットがないので,CPUから見たら無意味なことやらせるなっ!!って怒ってまじめに実行してくれていないのかも^_^;