質問: d0 + d1 + d2 + d3; stopTimer(); ``` 以上のようなコード(これは4つバージョン)でかかる時間を計測し、2,4,8,16,32,64のバージョンもそれぞれ試して、その実行時間の差を比べます。 するとコード内の演算子(+,=,<)の数が異なるので、実行時間い差が生じます。 例えば変数が2個の場合は、 「=」が 3N/3 + 4回 「+」が 5N/2 + 1回 「<」が 1N/2 + 1回で 合計で,(9N/2 + 6)回演算が行われていることになります。 また、変数が4つの場合は、合計で(15N/4 + 10)回の演算が行われているので、この演算の回数に依存するので、変数が増えれば増えるほど実行時間が短くなるのかなと思っていました。 しかし、この変数を32個、64個と増やしていくと、32個のときよりも64個のときのほうが時間(+0.002秒ほど)がかかってしましました。 演算の回数自体は64個のもののほうが少ないので、直感的には64個のもののほうが32個のものよりも短くなると思うのですが、どうしてこんな結果が出るのでしょうか。 【補足に補足】 回答していただいた3人の方、ありがとうございます。 「C++はコンパイル時に最適化されるので、どんなふうに書いても、それは今回の質問内容に対する議論にはならない」と、あるのですが、まだちゃんと納得することができていません。 実際、段数が2回のときと4回のときの実行時間(10回行ったものの平均)は 2: 0.12299 4: 0.07963 となっており、この辺では大幅に効果が出ています。 どんなコードでも同じ挙動を示すものなら最適化され、最も良いもので実行されるのであれば、こんな風にはならない気がします。 また、僕は普段はC++を使っていないので、友だちに聞いた方法でコンパイルしたのですが、それは「windowsPCのコマンドプロンプトでcl ファイル名.cppを実行」するものです。このコンパイルの方法が最適化されたものなのかどうかはわかっていません。 またソフトウェアパイプラインのwikiのページでは、こんな記述がありました。 > > パイプライン化された(命令パイプラインの記事を参照)プロセッサの実行ユニットで効率良く実行できるように命令スケジューリングできるよう、プログラムを変形するという手法である。高度なコンパイラではコンパイラ最適化により行われることもあるが、一般にはしばしば、多数回繰り返されるが1回の処理内容がごくわずかなループ(画像処理や信号処理などには多い)について、手作業で、一種のアウト・オブ・オーダー実行のようなプログラムの書換え(ループの繰返しをまたいで、コードの順序を前後に入れ替えることが多い)を行う。 > > > と、あります。以上の結果と、このページの説明を見ると、最適化されておらず、やはり変数の数を変えることで実行時間に影響があるのかなと感じます。 そして、その上で僕が知りたくて四苦八苦しているのは、以上のことが前提としてある上で、「なぜ64個の方が32個のものより時間がかかったのか」なのです。 長々と、そして何度も補足してすみません。 どなたかわかる方がいらっしゃれば教えて頂けるとうれしいです。 よろしくお願いします。
回答: 32→64で、ループ1回分のコードサイズは確実に長くなります。そのため、命令キャッシュに収まりきらなくなった、或いは命令キャッシュミスの発生頻度が上がった(そのプログラム実行中、他のコード...OSや種々の割込み処理等...も動作するのだから)、可能性を挙げます。 > > ソフトウェアパイプラインのwikiのページでは > > > このページにも「ループ部分のコードは12倍以上増加する(使用するメモリ量に影響するだけでなく、キャッシュ性能にも影響する。コードの膨張参照)」という記述があります。 ただ、こちらはそのプログラムコードのサイズがわからないばかりか、命令キャッシュの具体的なサイズを把握しておらず、机上の思いつきであることを予めお断りいたしますw