2011-03-29 7 views
3

コンパイラがソースコードを最適化するためのリストがあれば誰でも知っていますか?私は例としてGCCが好きです。コンパイラが最適化を行うのに役立つコードを書く

私はプログラマがコードをどのようにすべきか知りたいのですが、良い最適化を得てコンパイラが最適化するのを助けてください。プログラマによる最適化の中には、コンパイラがより良い最適化を行うのを避けるものがあります。

例:

replace 
for (int i = 0; i < n - 1; i++) 
by 
int n2 = n - 1; 
for (int i = 0; i < n2; i++) 


for (int i = 0; i < n/2; i++) 
by 
int n2 = n/2; 
for (int i = 0; i < n2; i++) 



for (int i = 0; i < obj.calc_value(); i++) //calc_value() will return the same result with obj remaining unchanged. 
by 
int y = obj.calc_value() 
for (int i = 0; i < y; i++) 

読んで理解するために、コードをシンプルにすることが重要です。

おかげ

編集:

その他の例:

  • インライン関数
  • 削除再帰真剣
+0

コンパイラも人です! :-)あなたのコードが読んで理解しやすいなら、彼らはあなたの意図を見て、そのコードを生成します。あなたが以前に見たことのない "スマートな技"を行うなら、あなたの大学生もコンパイラもそのことで何をするかを知ることはできません。 –

答えて

13

、単にコンパイラにそれを任せます。私はgccが "狂った" -O3レベルで出力するコードを見てきました。これらの最適化エンジンを書いた人がエイリアンであるか、実質的に遠い将来の時間であることが証明されています。

私はまだregisterまたはinlineが私のコードの性能に大きな違いをもたらしたという状況を見ていません。それはそれがでないことを意味しません、コンパイラの作家は、プロセッサからのパフォーマンスの最後のオンスを抽出することになると私たち単なる人間よりもはるかに多くのトリックを知っていることを意味します。

最適化が行われる限りは、実際の問題がある場合にのみ行う必要があります。つまり、コードをプロファイリングしてボトルネックを発見することですが、より重要なことは、コンテキストが遅いとは見なされない操作を最適化しないことです。ワンショット操作が10分の1秒か100分の1かどうかは、ユーザーにはゼロになります。

そして、時には、読みやすくするための最適化はさておき、これはあなたのためだけの気の利いたトリックのgccいれるとして、あなたは


:-)できる最善の一つです。これは、(-O3時)にコンパイル

static int fact (unsigned int n) { 
    if (n == 0) return 1; 
    return n * fact (n-1); 
} 
int main (void) { 
    return fact (6); 
} 

:階乗を計算し、それを返すことになって、次のコードを考えてみましょうそうですねそれ

main: pushl %ebp   ; stack frame setup. 
     movl  $720, %eax  ; just load 720 (6!) into eax. 
     movl  %esp, %ebp  ; stack frame 
     popl  %ebp   ; tear-down. 
     ret      ; and return. 

、gccがちょうどコンパイル時にそれをすべてうまくいきます-O0(ナイーブ)バージョンと

int main (void) { return 720; } 

コントラストこの:との同等に全部をオン

main: pushl %ebp    ; stack 
     movl %esp, %ebp   ; frame 
     andl $-16, %esp   ; set 
     subl $16, %esp   ; up. 
     movl $6, (%esp)   ; pass 6 as parameter. 
     call fact    ; call factorial function. 
     leave      ; stack frame tear down. 
     ret      ; and exit. 

fact: pushl %ebp    ; stack 
     movl %esp, %ebp   ; frame 
     subl $24, %esp   ; set up. 
     cmpl $0, 8(%ebp)  ; passed param zero? 
     jne  .L2    ; no, keep going. 
     movl $1, %eax   ; yes, set return to 1. 
     jmp  .L3    ; goto return bit. 

.L2: movl 8(%ebp), %eax  ; get parameter. 
     subl $1, %eax   ; decrement. 
     movl %eax, (%esp)  ; pass that value to next level down. 
     call fact    ; call factorial function. 
     imull 8(%ebp), %eax  ; multiply return value by passed param. 

.L3: leave      ; stack frame tear down. 
     ret      ; and exit. 
+5

+1は「可読性を最適化することがあなたができる最良のもの」です。新しいコンパイラが行う最適化の種類に関するドキュメントを参照したいと思います。私はいくつか(ループのアンロール、スタックではなくレジスタの使用、インライン展開、テール再帰のアンロールなど)を読んだことがありますが、それらはすべて明白で古代のトリックです。 –

+1

@Merlyn Morgan-Graham:この本は非常に貴重だと思います(もしあなたがコンパイラを書いているのなら)[Advanced Compiler Design Implementation](http://www.amazon.com/Advanced-Compiler-Design-Implementation-Muchnick/dp/ 1558603204/ref = pd_rhf_shvl_3)しかし、私はこれを買って以来、しばらくしているので、もっと近代的な本があると確信しています。 –

+0

ループ条件から 'n - 1'を最適化できると思いますか? :-) –

3

提案されたすべての改善点は、ほとんどすべての最適化コンパイラが行う基本的な最適化の例であるLoop-invariant code motionの例です。

実際のコンパイラで実行される最適化の範囲は、これらの例よりはるかに進んでいます。上にリンクされたWikipediaの記事には、さらに読むためのリンクがいくつかあります。

+0

+1。 –

0

あなたが投稿したコードについては、私はpaxdiabloの答えに同意します。多くの場合、ヒントなしでコンパイラは非常にうまく最適化できます。

テンプレートメタプログラミング

あなたは、コンパイラの最適化を支援するために探しているなら(との理由持っている! - プロファイル、プロファイルを、プロファイル)、私が見た中で最も潜在的に有用なトリックがtemplate metaprogrammingです。

Boost has some direct support for template metaprogramming

有用な例は、ソースコードにそれらの操作を残しながら、実行される操作の数を減らすテンプレートのメタプログラミングされた行列演算ライブラリです。また、コンパイル時に一部の操作を完全に評価します。

ここでGoogleで現れるものの最初のです:http://arma.sourceforge.net/

のConst正しさ

それが簡単にバグプルーフあなたのコードを助けることができるので、あなたは、調査すべきもう一つは、const-correctnessです。追加の利点はit can sometimes help with compiler optimizationsです。

const-correctnessとtemplate-metaprogrammingの両方をマスターするのはかなり難しいですが、非常に便利です。これはC++の大部分です:)

0

ここで「最適化しないでください」と言っても、(Cの場合は)コンパイラがより良いコードを作成できるように常に助けてください。

コンパイラは、利用可能なパイプラインと実行ユニットを最適に使用するために、戦術的にコードを注文する際に、ほとんどのプログラマより優れています。言いましたが、コンパイラは戦略的なプログラミングレベル、つまり個々の手順上のレベルではあまりよくないことを指摘することも重要です。

パフォーマンスの低いソフトウェアは、パフォーマンスの高いソフトウェアよりもはるかに一般的です。オプティマイザではあまり認知されていないことの1つは、パフォーマンスの低いソフトウェアを書くことは(明らかに)可能であるため、優れたパフォーマンスを書くことも(明らかに)可能であることです。コンパイラは錬金術ではありません。ガベージソースコードをフィードして、ガーベージマシンコードを生成します。それらに有能なソースコードを提供すれば、有能なマシンコードを確実に生成できます。

私は最適化のテーマについて相反しています。一方で、パフォーマンスの問題が特定されている場合(ほとんどの場合、開発が完了に近づいている)、戦略的レベルでの作業が必要であるため、通常は大幅な改善(例えば100%以上)は遅すぎますのための時間)。一方、それが早く完了した場合、「完全なパフォーマンスの画像」は利用できないため、「最適化しない」とは、有効なデータがないため最適化するのが早すぎると言うでしょう。最適化は、あまりにも頻繁に、不完全に構築されたソフトウェアを救済するために、あるいは受け入れテストを通じて人生支援として恐慌で行われることが多すぎます。正のコンテキスト(良いコードをより効率的に実行させる)での最適化は、多かれ少なかれ聞こえません(少なくともここでは?)。

私はうまくいくコードを書くのが楽しいです。私のコードは読み込み可能ですが、より良いパフォーマンスを発揮することがわかっているため、最初の経験から特定のコード構造を選択します。また、私は自分のアプリケーションを開発の初めから計測し、自分自身を測定し、開発が進むにつれてパフォーマンスを監視することができます。

関連する問題