• ベストアンサー

インライン展開でコンパイラが何をやっているのか知りたいです

インライン展開すると、関数の呼び出しオーバーヘッドが小さくなることはわかるのですが、インライン展開した場合としていない場合と、なぜ関数呼び出しのオーバーヘッドがなくなるのかアセンブルレベルでの違いがよくわからないです。 関数をインライン展開した場合、コンパイラはどのようにコンパイルするのか、そしてその関数実行時の振る舞いがインライン展開なしの場合とどう違うのか、わからないので教えていただけませんか? 以上、よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • ymmasayan
  • ベストアンサー率30% (2593/8599)
回答No.1

簡単に言うと 1.引数のコピー処理 2.CALL命令 3.戻り値のセット処理 4.RET命令 の分が多くなります。 変な例えですが、冷蔵庫を家の外に置いておくと、上着を着て履物を履いて出て行き、戻ると履物を脱いで、上着を脱ぐといったようなものです。 上の1の引数のコピー処理はCall by value(値渡し)の場合におこります。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.4

#2: loopのun-rollとinlineは別物じゃないですか?

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

引数や返却値のコピーとサブルーチンの往復に関しては既に別の方が回答されていますが、それ以外にも違いが現れます。 インライン関数を呼び出す部分をコンパイルする際、コンパイラは呼び出そうとする関数の中身のことまで全て分かることになります。これによって関数の枠組みを超えた最適化が可能になります。 関数の枠組みを超えた最適化は、引数に定数式を渡した場合等に最も顕著になり、場合によっては関数の呼び出しが単なる定数として展開される可能性もあります。 他に、例外処理に関しても大きな影響が現れます。例外指定によって明示的に例外が発生しないことを宣言しない限り、通常の関数であればあらゆる例外が発生するものとして、それに対応するために処理を展開する必要がありますが、インライン関数であれば、関数の中身が分かっていますから、可能であれば例外が発生しないものとして扱うことが可能になります。これによって(多くの場合)速度もサイズも大幅な改善が可能になります。

全文を見る
すると、全ての回答が全文表示されます。
回答No.2

単純な例でいいますと、こうなります。 for(i=0;i<10;i++) { func(); } は funcの中身;funcの中身;funcの中身;funcの中身;funcの中身;funcの中身;funcの中身;funcの中身;funcの中身;funcの中身; のようになります。 上記の例ですと、i変数を使ってループしていますが、i変数を加算したり評価したりする部分、 そして、関数のcall、引数のセット等、ret がなくなり、その分だけ速度が向上します。 しかし、funcの中身が大きかったりループ数が多ければ 命令がL1キャッシュに入りきらず、かえって速度が低下することがあるので コンパイラはそのあたりも自動的に判断します。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 手続きのインライン展開 基準

    コンパイラ型言語における手続きのインライン展開についてです。 例えばC++の場合、inline指定子をつけるなどしてインライン展開を促しますが, 長い手続きの場合はインライン展開されないと記憶しています。 お尋ねしたいことは2つあります。 1つ。1箇所でしか呼び出されない手続きの場合、どんなに長くても、インライン展開したほうがより最適なプログラムになるのではないか? 2つ。1箇所でしか呼び出されない手続きの場合、最適化モードでコンパイルするなりインライン展開指定するなりすれば、インライン展開は行なわれるか? 暇な時にでも、どなたか教えていただけたら幸いです。

  • インライン関数

    インライン関数として認識されなくても、通常の関数として実行されるのなら、プログラムする際にはすべての関数にinlineと書けばいいと思います。 インライン関数を使えば実行速度が上がる。それなら何故コンパイラ側で通常の関数すべてをインライン関数として認識しないのかがわかりません。inlineと書く手間が省けるので。 lnline関数として認識しようとしたができず、通常の関数として実行する時は、通常の関数を普通に実行するときよりも実行速度が遅くなるのでしょうか?もし、遅くならないのならすべての関数をinline関数として書けばいいと思います。どうなんでしょうか?お願いします。

  • GNUコンパイラとIntelコンパイラの違いについて

    今回fortranとC言語で書かれたWindows用プログラムをLinux用に移植することになりました。GNUのコンパイラを使用し無事コンパイルできたので実行したのですが"Segmentation fault"となりうまく実行できませんでした。そこで試しにIntelのコンパイラを使用しコンパイルしてみたところGNUのときとは違い"Segmentation fault"とは出ず、プログラム内のエラーチェックに引っかかり止ってしまいました。同じソースコードにもかかわらず止まる箇所が異なります。 今まで考えたことがなかったのですがGNUとIntelのコンパイラの違いはなんなのでしょうか?また、この二つ以外にいいコンパイラはあるのでしょうか?

  • eclipseの設定のJREとコンパイラの違い

    eclipseの設定で、インストール済みのJREとコンパイラの違いについて教えて いただけないでしょうか。 自分で調べてみた限りでは、、、 インストール済みのJREは、Javaプログラムの実行、デバッグに使用される。 コンパイラは、Javaプログラムのコンパイルに使用される。コンパイラ自体はeclipse 内部のものを使用しており、コンパイラ準拠レベルを指定することにより、指定した Javaのバージョンでコンパイルを行うことが可能。 上記の仕様だと、例えばインストール済みのJREのバージョンを1.6、コンパイラ準拠レベル に1.4を指定したとします。こうした場合、 String s = "hoge"; if(s.isEmpty()) { ・・・・ というコードはコンパイルエラーになるはずです。(String#isEmpty()は1.6から導入) コンパイルエラー⇒クラスができない⇒実行できない、という流れを想定していたの ですが、実際は、エディタ上でエラーになっておらず、コンパイルもでき、実行もできました。 インストール済みのJRE、コンパイラともに1.4を指定すると、エディタ上でエラーに なっていたし、コンパイルも行われていませんでした。 コンパイラ準拠レベルとはいったい???という状態です。 どこかに詳しく説明されているサイトなども教えて頂けるとうれしいです。 宜しくお願いします。 OS:Windows7 HomePremium eclipse:eclipse-jee-indigo-SR1-win32-x86_64.zip

    • ベストアンサー
    • Java
  • コンパイラ、インタプリタ、クロスコンパイラについて

    インタプリタについて質問があります。 色々と調べたところ、perl、php、rubyなど、ソースをインタプリタで実行する言語の利点は以下なのだと思います。 ソフトを作っている環境と実行環境の間でcpuやos等が異なる場合は、 ソースは互いに異なる機械語に翻訳されるので、翻訳は実行環境で行わなければならない。 その際、コンパイラの場合はわざわざ手動で翻訳を実行しなければならないが、 インタプリタの場合は勝手に実行時に翻訳してくれるので楽。 1.それで質問なのですが、 コンパイラは環境に対応した機械語を出すらしいですが、 何故そんな事ができるのでしょうか。 コンパイラが、自身が置かれた環境を分析して、それに対応した機械語を出すのでしょうか? それとも、そもそも環境毎に対応したコンパイラを使うという事でしょうか? 2.また、世の中にはクロスコンパイラというものがあると聞きました。 クロスコンパイラがあれば、ソフトを作っている環境でそのままコンパイルできるので、 インタプリタはいらないのではないでしょうか? クロスコンパイラの短所や長所などを教えてほしいです。 3.翻訳後の話として、機械語はcpuやosによって違うという話ですよね。 つまり、機械語にコンパイル済みのソフトを配布する際は環境毎に対応したソフトを それぞれ配布しなければならないのですよね。 しかし、ネット上でダウンロードできるフリーのソフトなんかは、 特定のOS向け、あるいはOS別に違うファイルを配布、というのはよく見かけますが、 cpuやその他の環境毎に配布物を分けているのは見たことがありません。 機械語は、本当にos以外にも依存するものなのでしょうか?

  • コンパイラの最適化オプションについて

    あるプログラムを実行したさいに、コンパイラの最適化オプションをなしにすると、正しく実行できるのですが、最適化オプションをありにするとcoreダンプしてしまいます。 このような場合、プログラムにバグがあると考えるのが妥当だとは思うのですが、コンパイラによっては、このようなことも当然ありうると考えたほうが良いのでしょうか? 識者の方がおられましたら、アドバイスをお願いします。

  • コンパイラの違いについて

    こんばんはです。 実は、ビジュアルスタジオで組んだCソースをBolrand C++コンパイラで組んでるPCで実行すると、違った結果が出てきてこまってます。 visualstudioでもBolrandでも、ソースのコンパイルはエラーなしでとおります。 しかし、実行すると、結果が違うのです。これって・・・? 結果と言うのはstrcmpでかえってくる数字なのですが、studioでエグゼつくって実行すると、0も1もー1も返ってきて判断分岐できるのですが、Bolrandの方でエグゼつくって実行すると、0しか返ってきません。なので、分岐は0の時だけの対応しかできないのです。 もっとくわしくいいますと、studioの方もBolrandの方もコンパイルはプロントでおこなっており、studioはcl test.c Bolrandはbcc32 test.c と言う具合に行ってます。 もしかして、古さの違いとかってあるのです?? 昔は構造体のコピーってa = bってできなかったではないですか? 今はa = bできますよね。そういう感じなのでしょうか?? ご存知の方いらっしゃいましたらアドバイスいただきたいです。 よろしくおねがいいたします。

  • コンパイラによってエラーが出たり出なかったり

    構造体をポインタでつなぐリスト構造を使ったソースを書いて、Borland C++ Compiler 5.5 でコンパイルしたものを実行するとエラーで止まってしまいました。 コンパイル時には何も警告が出ませんでした。 しかし、ソースを何度見てもバグらしいコードが見つからなかったので、試しに Microsoft .NET Framework SDK でコンパイルしてみたところ、こちらも警告も出ずにコンパイルが通って、実行してみたらこんどは正常に動作しました。 コンパイラによって、実行時にエラーが出たり出なかったりするということは初めてなのでその原因を知りたくて質問しました。 どういった場合にこのようなことが起こるのでしょうか。 Borland C++ で出たエラーは、おそらくセグメントエラーだと思います。 今のところ正常に動いているのですが、なにかデンジャラスなコードを書いてしまった気がして気持ち悪いです。

  • コンパイラ、その周辺の質問

    C言語を勉強していて、いまいちわからなかったことを、ないがしろにしていたのでここで質問させてください。 ・あるプログラムをコンパイルするとまず機械語に翻訳されオブジェクトファイルができ、リンクすることでライブラリに登録されている関数のオブジェクトファイルと結合させ1つの実行ファイルを作るのですよね?(ここまでまちがいない?)  例えばprintf()を使ったときコンパイラはどのようにしてそのprintf()のオブジェクトファイルを探しているのかよくわかりません。ライブラリ(.lib)の働きも良くわかっていません。 VC++を使っておりますが、自作の関数をライブラリに登録する方法もできれば教えていただきたいです。 よろしくお願いします。

  • templateクラスの宣言と定義を、別々のファイルに分けたい

    こんばんは。 templateを利用したクラスについての質問です。 通常、テンプレートクラスのメンバ関数は、その定義部分をインライン展開するべき、とのことですが… なんとかして宣言部と定義部を別々のファイルに分ける事は出来ないでしょうか? テンプレート変数をクラス内で共有したいため、テンプレート関数ではなく、テンプレートクラスで上記の事を実現したいのです。 「コンパイラによっては、インライン関数でなければならない」という記述を見かけたので、 コンパイラによってはインライン関数でなくても構わないのでしょうか? 開発環境は WindowsXP-SP2 VisualStudio2005-SP1 C++コンソールアプリケーションです。