オーバーヘッドの最適化全般について学びたい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
stormrider

オーバーヘッドの最適化全般について学びたい

#1

投稿記事 by stormrider » 13年前

 お世話になっております。
 今回は何ができなくて困っている、ということではありません。
 処理をより高速に行うために一般論として心がけられることは何か、ということに興味を持っています。
・ループ内で何回も変数を定義している場合、外に括り出す。
・論理和や論理積の条件の際、より緩い条件を後ろに持ってくることで、計算回数を減らす。
といった技法について詳しく知りたいのです。
 たとえば、

コード:

float a = 0.0f;
for( int n = 0; n < 10; n++ ) {
  a += 35.0f / 3.3f; 
}
というコードがあった場合、35.0f / 3.3fをループ外で定義した変数に代入してループ内で計算を省いた方が速いのか、それともこの程度の計算回数ならわざわざ余計に変数を定義する方がコストが大きいのか?また、ループの回数が影響するのなら、どこが分岐点となるのか?

 ここまで細かいことが影響するような精度のプログラムを組んではいないですが、作法としてどのようなコードがより無駄がないのか、その原理はなぜか、ということを調べたいのです。
 環境やコンパイラによって変わるのでなんとも言えない、というところもあるかとは思いますが、こうしたテーマについて詳しく(できれば初心者にもわかりやすく)書いてあるサイトや書籍があったら紹介してください。

アバター
うしお
記事: 56
登録日時: 14年前

Re: オーバーヘッドの最適化全般について学びたい

#2

投稿記事 by うしお » 13年前

こういったミクロなレベルでやれる高速化は殆んどの場合無意味に終わると思います。
パフォーマンスについて効率的に学ぶのであれば、「計算量オーダー」という考え方を学ぶのをオススメします。
さまざまな言語にも応用できる考え方です。

が、その上で今回なケースについて考えてみます。

まず、35.0f / 3.3fはまともなコンパイラなら定数に最適化されるでしょう。

また、
for( int n = 0; n < 10; n++ )
これはSTLのイテレータがらみで考えた場合、
for( int n = 0; n < 10; ++n )
とするほうがパフォーマンスに優れる場合が多く、私はいつも前置インクリメント構文を使います。

最適化はとにかく実測値だけが信じられます。
コンパイラの最適化を想像するというのは、徒労に終わるだけでしょう。
また早すぎる最適化は諸悪の根源です。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: オーバーヘッドの最適化全般について学びたい

#3

投稿記事 by softya(ソフト屋) » 13年前

極端な最適化は難読なコードを生みかねません。
それと小手先なテクニックよりも最適なアルゴリズムの方が効果的な場合が多いです。
うしおさんの言うように実測することが一番大事です。
ただし、CPUキャッシュの効果とか様々な知識がないと実測値を生かすことができない場合も多いですよ。[語抜け修正]

>・ループ内で何回も変数を定義している場合、外に括り出す。
これは意味が無い可能性が高いでしょう。

>・論理和や論理積の条件の際、より緩い条件を後ろに持ってくることで、計算回数を減らす。
悪くはないですが、だらだらと&&するよりはif文を書いたほうが見た目がすっきりする場合もあります。

どうしても気になるなら。
・暗黙・明確な型変換を出来るだけ行わないようにする。
・ループ回数が減るように工夫する。
・ループの深い所で関数呼び出しを避ける。
・構造体は出来るだけ参照渡しを行う(ポインタは危険が伴うが)
・if文、3項演算子をできるだけ減らす。
・elseのないif文ならTRUEになる確率が高い条件を選ぶ。
・文字列での処理を極力行わない。
・出来るだけ狭いメモリ空間へのアクセスが多くなるように工夫する。
・if文やif文中の&&などのコストが同等だと理解する。
かなぁ。抜けがあると思いますが。
できるだけアセンブラレベルの分岐・関数呼び出し・変数のコピー・型変換・参照/更新アドレスの変動が起こらないように工夫することです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
GRAM
記事: 164
登録日時: 14年前
住所: 大阪

Re: オーバーヘッドの最適化全般について学びたい

#4

投稿記事 by GRAM » 13年前

「EfficientC++パフォーマンスプログラミングテクニック」
という本に(あくまでもC++についてでしたら)ある程度の一般論は載っているんじゃないかと・・・
その本も「こういう部分に着目するといいよ」的な感じで、結局「測れ」ということを言ってますが・・・

たかぎ
記事: 328
登録日時: 14年前
住所: 大阪
連絡を取る:

Re: オーバーヘッドの最適化全般について学びたい

#5

投稿記事 by たかぎ » 13年前

今回の件に関して言えば、一番確実な最適化は次のようにすることです。

コード:

float a = 35.0f / 3.3f * 10;
コンパイル時に計算できるものはコンパイル時に計算してしまえば、実行時のコストはゼロになります。
これは実測しなくてもわかります。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: オーバーヘッドの最適化全般について学びたい

#6

投稿記事 by ISLe » 13年前

Wikipediaに『コンパイラ最適化』というページがありました。
内容が分かりやすいか正確かという点は疑問が付きますけど、どんなものがあるかは分かるかと。

あとはコンパイラの最適化オプションひとつひとつの解説(リファレンス)をあたってみるとか。

stormrider

Re: オーバーヘッドの最適化全般について学びたい

#7

投稿記事 by stormrider » 13年前

 みなさんいろいろ教えていただきありがとうございます。
 実用性はあまり求めていませんでした。今は些細なメモリの切り詰めよりも可読性や保守性が重視されるらしい、ということは知識としては知っているのですが、「メモリ1バイトは血の一滴」と言われた時代に憧れがあり、趣味で知りたかったのです。
 どうも、コンパイラの内部処理をまずは調べていくのが一番良さそうですね。
 前置インクリメントのことや&&とifが同等など、知らなかったので勉強になりました。
 お勧めいただいた本も読んでみます。wikiも参考になりました。

 よろしければもう少しおつきあいください。
 2点わからなかったのですが、「早すぎる最適化は諸悪の根源」というのは、「可読性を犠牲にした最適化は」という意味以外に、処理を早くすること自体による問題が生じることもありえるのですか?
 また、「elseのないif文ならTRUEになる確率が高い条件を選ぶ。」、これは実は反対にfalseになる可能性が高い方が、中の処理をスキップできる=処理数が少なくなるので早いと思っていました。wikiにある「分岐は命令のプリフェッチを乱すため、性能低下の原因となる。」にあたるのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: オーバーヘッドの最適化全般について学びたい

#8

投稿記事 by softya(ソフト屋) » 13年前

wikiにある「分岐は命令のプリフェッチを乱すため、性能低下の原因となる。」
これは、命令パイプラインの動作を乱す為ですね。
「命令パイプライン - Wikipedia」
http://ja.wikipedia.org/wiki/%E5%91%BD% ... 4%E3%83%B3

if文でTRUEを多くしたほうが良いと言ったのは、このためです。
ただしTRUEの内容が重ければ、この限りではありません。

最近のCPUは分岐の予想をした上で投機的な命令プリフェッチも行いますので、CPUコアの設計ごとに実際の動作は異なると思います。
あんまり張り切って特定のCPUだけでチューンナップするとINTELでは速いがAMDでは遅いとか、INTELでも特定のコアのみ速いとかが起こりえます。

「分岐予測 - Wikipedia」
http://ja.wikipedia.org/wiki/%E5%88%86% ... 8%E6%B8%AC
「分岐先予測 - Wikipedia」
http://ja.wikipedia.org/wiki/%E5%88%86% ... 8%E6%B8%AC
「投機的実行 - Wikipedia」
http://ja.wikipedia.org/wiki/%E6%8A%95% ... F%E8%A1%8C

その他に使われているコンピュータアーキテクチャの例。
「レジスタ・リネーミング - Wikipedia」
http://ja.wikipedia.org/wiki/%E3%83%AC% ... 3%E3%82%B0
「アウト・オブ・オーダー実行 - Wikipedia」
http://ja.wikipedia.org/wiki/%E3%82%A2% ... F%E8%A1%8C

AMDのCPUをお使いなら無料で利用できる「AMD CodeAnalyst Performance Analyzer」ってのが命令オーダーまで見れます。
「AMD CodeAnalyst Performance Analyzer | AMD Developer Central」
http://developer.amd.com/tools/codeanal ... fault.aspx
VisualStudioに統合できるので楽は楽ですが、解析結果の意味を理解するのは大変だと思います。

【追記】
>処理を早くすること自体による問題が生じることもありえるのですか?

少しの修正で速度のチューニングが意味を無くす可能性があるので無駄に労力が掛かる可能性があるって所ではないでしょうか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

史上最悪のデスペナ
記事: 521
登録日時: 14年前

Re: オーバーヘッドの最適化全般について学びたい

#9

投稿記事 by 史上最悪のデスペナ » 13年前

便乗して質問があります。
RPGで最大HPをLv×1000とした時、
最大HPと現在のHPを比較する場合において
MaxHPという変数を用意したほうがいいのか、いちいちLv×1000を計算させたほうがいいか
どちらがPCにやさしいですか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: オーバーヘッドの最適化全般について学びたい

#10

投稿記事 by softya(ソフト屋) » 13年前

史上最悪のデスペナ さんが書きました:便乗して質問があります。
RPGで最大HPをLv×1000とした時、
最大HPと現在のHPを比較する場合において
MaxHPという変数を用意したほうがいいのか、いちいちLv×1000を計算させたほうがいいか
どちらがPCにやさしいですか?
どちらが分りやすいかを気にするべきで、一回あたり1ns(ナノ秒)程度の差しかない時間を気にしても仕方有りませんよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

史上最悪のデスペナ
記事: 521
登録日時: 14年前

Re: オーバーヘッドの最適化全般について学びたい

#11

投稿記事 by 史上最悪のデスペナ » 13年前

ふむふむ。
いくらちりが積もって山となってもぎりぎり知覚出来そうなm秒になるにも10^6個も必要になりますしね。
PCの動作する原理が分かってないとそういうことを理解するのが難しい気がしてきました^^;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: オーバーヘッドの最適化全般について学びたい

#12

投稿記事 by softya(ソフト屋) » 13年前

人間が知覚出来る限界は10ms~15msぐらい。モニターの描画周期は16.6666…ms。ですので1ns差は表面化しません。

>PCの動作する原理が分かってないとそういうことを理解するのが難しい気がしてきました^^;

1つの命令動作は1ns以下なので、通常はあまり気にしなくて良いです。
ゲームだとGPUの負荷のほうが大きすぎる場合もありえるので、処理落ちがCPUが原因じゃない場合もあります。
実際に気にするとしたら、1フレーム当たり10^6回を超えるループを行なっている所があった場合でしょう。そういう所を気にしてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stormrider

Re: オーバーヘッドの最適化全般について学びたい

#13

投稿記事 by stormrider » 13年前

遅くなりましたが、返信いただいた方々どうもありがとうございました。
追加の質問も一段落ついたようですので、これで閉じさせていただきます。

閉鎖

“C言語何でも質問掲示板” へ戻る