開発環境;Windows2000sp4/VC++6sp6/SDK
ソースのモジュール分割と処理速度との関係について質問です。
あるプロジェクト「FooProject」があるとき、あるクラスを
別モジュールで宣言・定義するとします。
このとき、ケース1のようにヘッダファイルでインラインで
定義した場合とケース2のように別ファイルでインライン定義
した場合は同じことだと認識しています。
ところで、ケース2で、「inline」を書かなかった場合、
インライン化され得ないため、処理速度低下の恐れはありうる
と考えてよいでしょうか。
↓
是だとすると、hoge.hを複数の.cppでincludeする場合、ケース1
だと複数定義エラーとなるため、ケース2のようにせざるを
得ないということでしょうか。
↓
気になるのは、是のとき、関数をインライン化できないため、
オーバーヘッドなどによって遅くなる恐れがあるだろうか、
と言う点と、その回避策はあるのか、という点です。
ご存知の肩が折られましたら、お教えください。
よろしくお願い致します。
なお、inline を記述した場合に、その関数はインライン化される
期待は充分にあると仮定してください。
■ケース1■
//--[ hoge.h ]--
class CHoge
{
public:
CHoge(){}
void doSomething(){
// snip
}
};
//--[ fooproject.cpp]--
#include "hoge.h"
■ケース2■
//--[ hoge.h ]--
class CHoge
{
public:
CHoge();
void doSomething();
};
//--[ hoge.cpp ]--
CHoge::CHoge();
inline void CHoge::doSomething(){
// snip
}
//--[ fooproject.cpp]--
#include "hoge.h"
> ところで、ケース2で、「inline」を書かなかった場合、
> インライン化され得ないため、処理速度低下の恐れはありうる
> と考えてよいでしょうか。
あり得ます。
ただし、コンパイラの最適化性能によっては、inline を書いてない関数を勝手にインライン化することもあり得ます。
> 気になるのは、是のとき、関数をインライン化できないため、
> オーバーヘッドなどによって遅くなる恐れがあるだろうか、
> と言う点と、その回避策はあるのか、という点です。
非仮想関数コールの呼び出しオーバーヘッドさえ嫌うのであれば、関数呼び出しをやめてべた書きするとか、アセンブラでゴリゴリ書くとかになっちゃいそうな気もしますが。
インラインでない関数の場合、オーバーヘッドが出てしまうのは
当たり前の話でそこに関数コールがある限り呼び出しのオーバーヘッドは
存在すると思います。
問題は、そのオーバーヘッドが無視してよい程度の物なのかと言う話なので
これはシステム全体のパフォーマンスを見た時にそのオーバーヘッドによる
コストが全体の処理コストのどの程度を占めているのかによるわけです。
なのでいつも同じ視点で考えるのはどうかと思います。
通常の環境で一般的なアプリケーションを対象に考えた時は
関数化した時のメリットの方が大きい場合がほとんどでしょう。
その部分に拘るのはそこに拘らないと期待するパフォーマンスが得られない
ようなケースに限定されると思います。
そういう意味では、その関数の呼び出しのオーバーヘッドが
処理コスト全体に及ぼす影響が大きいとはじめから分かっているのであれば、
はじめからインライン化すれば良いわけでその場合は意識して行っている
わけですから、管理をきちんとすればよいのではないかと思います。
inlineを書き忘れてしまったらどうしようと言う話ならそのままでは多分、
どうしようもないと言うのが回答なのかなと思います。
ただ、わざわざインライン化しているということは、そこに注意がいっている
と言う事なのでそういう重要な部分であれば、チェックを強化するとか
運用方法で何とかすると言うのはありなのでは?
あとはマクロくらいかなぁ。
もちろんヘッダーファイルに記述と言う事になるし、型安全性は無いしで
問題ありありですけれど。
ちなみに最近のPentium4とかのCPUであれば、正直この手の悩みは無意味です。今のCPUは昔の8086とかに比べてはるかに早くて複雑なので、この手のことを悩んでいるプログラマーの存在なんか無視して、猛烈な速さで処理が進んでいきます。
イメージ的には例えinlineにして1早くなるとしても、そもそもCPUは10000000ぐらいの速さで進んでいるので、1の効率化なんてゴミみたいなものです。また簡単にinline出来るぐらいの関数であれば、
>コンパイラの最適化性能によっては、inlineを書いてない関数を
>勝手にインライン化することもあり得ます。
こうなりますし。
本当に高速化したい場合はCPUのアーキテクチャを理解して、アセンブラでゴリゴリ書くしかありません(もしくはSSEの使用とか)。この場合もPen4とPen3でアーキテクチャが違うので、起動時にCPUの種類を調べて、呼び出す関数を変える…などをしないといけません。
結局現在のCPUでは大まかなアルゴリズムレベルで最適化するか、逆に細かなアセンブラレベルで最適化するかの2選になり、inlineの使用の有無でどうかなることはほぼありません。
んー、四の五の言わんと、何通りか書いて試してみりゃいいんじゃないかしら。
# 結局"ほとんど変わんなかった"に一票
> 結局現在のCPUでは大まかなアルゴリズムレベルで最適化するか、
> 逆に細かなアセンブラレベルで最適化するかの2選になり、
> inlineの使用の有無でどうかなることはほぼありません。
基本的にこれに同意。
ちなみに、
void doSomething(){
// snip
}
ここにどんな処理が入るのか。どの程度の数が展開されるのか。
仮に、inline展開でコード領域が膨張してコードキャッシュに入らなくなると、
もっとひどいペナルティを受けることになる可能性もあったりしますが。
個人的には、アセンブラの実行ステップ数が多少多かろうが、少なかろうが、
うまくキャッシュに乗ってるか乗らないかの方が大事なんじゃないかと。
# アセンブラで苦労する前に、コンパイラを ICC に変えてみるとか。
# 昨今のコンパイラより効率のいいアセンブリ書く労力はいかほどか。
>最適化するかの2選になり
「2択」の間違いでした。
ちなみにもし現在のCPUにおける最適化がどういうものか興味があるのなら、この本なんかが良くまとまっています。
MMXテクノロジ最適化テクニック
小鷲 英一
http://www.hondana.org/kmt-t/4756107974.html
もっともこの本自体はPen2辺りまでを対象にしていますので、現在のPen4には(そのままでは)通用しません。ただ「入門」としては適していると思います。
ご回答ありがとうございます。
■質問の意図
今、インラインで書いているクラスを、モジュール分割してみたのですが、
そうすると、hoge.cpp 内で inline と記述するとリンクエラーが出て、
inline を外すとリンクエラーがなくなったので、モジュール分割をしない
→モジュール分割をするをとしただけで、速度低下の恐れがあるのでは
ないか、という考えに至ったため、質問しました。
■まとめ
無論、キャッシュとかボトルネックとかといった話もあるでしょうが、
単純に、語弊を恐れずに言ったとき、このような場合は、
hoge.h でインラインでクラスを書いた場合
よりも
hoge.h/hoge.cpp とクラスの宣言と定義を分けた場合
の方が処理速度が低下する恐れがあるといえると解釈しました。
■補足
やってみりゃいいという言葉もありますが、机上の理論に過ぎないと
しても、お話を伺ってみたかったため、質問しました。
想定される実行環境は、Win95〜XPで、高速なPCはもとより、
低速なPCでも少しでも早く動くようなソースを書くための考察
といったところでしょうか。
# 「ICC コンパイラ」でググってみましたが、VC++のプラグイン
# として動作するんですね。初耳でした。
# http://www.xlsoft.com/jp/products/intel/compilers/icppwin.html
# でも当方、VC++6 standard なので使えませんね。。
# いずれにしろアセンブラは関係ありませんね。
# 「高速化したい」が主眼なのではなく、ソースのモジュール分割と
# 処理速度の関係について伺いたかったので。
# 「MMXテクノロジ最適化テクニック」ありがとうございます。
# 今度本屋に行った時にでも見てみたいと思います。
## ちなみに、VCは standard なのでプロファイラもありません・・・。
メンテナンス性とかを考えると、モジュール分割した方が、
コンパイル速度も向上して良いのですが、ちょっとした速度を
気にする場合は分割しない方が良いことが分かりました。
皆様、どうもありがとうございました。
良いお年をお過ごしください。
># いずれにしろアセンブラは関係ありませんね。
># 「高速化したい」が主眼なのではなく、ソースのモジュール分割と
># 処理速度の関係について伺いたかったので。
やはり見事に勘違いされてますので、おせっかいを承知で補足。
Pen1&Win95の低速PCでもモジュール分割して速度が遅くなることはありません。厳密には遅くなるかもしれませんが、それは1万行のソースで全て非inlineからinlineに変えても、0.00001秒程度の速度低下です。その程度の速度低下ではメンテナンス性を下げてまで分割しない理由にはならないでしょう。なると思うならご勝手にどうぞ。
>想定される実行環境は、Win95〜XPで、高速なPCはもとより、
>低速なPCでも少しでも早く動くようなソースを書くための考察
>といったところでしょうか。
inlineがこれに効果あると思っている段階で、既に完全に勘違いしています。上記の本を読めばどう勘違いしているか良く分かると思います。
解決チェックを付け忘れたので戻ってきたのですが、また回答が・・・。
シオさん、ご指摘感謝。
効果云々とかではなく、そうなる可能性があるかどうか、
の確認をしたかっただけで、その意図がご理解いただけなかったのは
残念ですが、確認はできましたので、感謝しております。
# 実際のコード使用上は、モジュール分割して使う方向で
# 行きたいと思います。
また質問することがあるかと思いますが、その際には
またよろしくお願い致します。
> hoge.h/hoge.cpp とクラスの宣言と定義を分けた場合
> の方が処理速度が低下する恐れがあるといえると解釈しました。
低下するというよりは、どちらかというとinlineの方が例外的なものであって、
注意深く inline 化すると、若干最適化できる可能性があるかもしれない、
くらいの認識の方が一般的な気がしますが...。
# おふとぴ
> でも当方、VC++6 standard なので使えませんね。。
# standard だと、確かコンパイラによるオプティマイズがありませんね。
# とすると、実際の高速化を意識するなら、コンパイラを差し替えるだけでも
# 最適化が利いてかなり高速化しそうな気がします。
# 無償でもVC++2003Toolkitとかありますし。
> 低下するというよりは、どちらかというとinlineの方が例外的なものであって、
> 注意深く inline 化すると、若干最適化できる可能性があるかもしれない、
> くらいの認識の方が一般的な気がしますが...。
元のソース(インラインでかかれたクラス)から比較した場合についての
表現なので、一般的に、と言われると、そうなのですか、としかいいようが
ないですね。
# 一応、VC++2003アカデミックもありますが、VC++6から移植するのが
# 結構面倒なので、VC++6で、としています。
# VC++2003って、コンパイル速度も劇速だし、マクロもインテリセンスが
# 利くので、便利ですよね。いずれ.NETに移行したいとは思っていますが…。
厳密に言えば、遅くなるけれどそれがパフォーマンスにどの程度影響するかどうかは
システム全体の構造とかによるので一概には言えない。
但し、一般的にはこれを気にしてモジュール分割を躊躇うほどの物ではない。
という結論でいいのではないですかねぇ。
学術的にとか、理論的にとか、厳密にと言う但し書きがつけば、
確かに影響があるといえなくは無いのですけれど。
実際に仕事でシステムを組むような場合には、
その影響を気にするよりもメンテナンス性に重きを置く場合が大半だと
考えればいいのではないでしょうか。
経験的に言ってもこれが直接影響を与えてパフォーマンスの足を引っ張ると
言うケースは稀だと思いますし。
絶対に無いとは言いませんけれど。
ツイート | ![]() |