C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[8]: コンパイラーの最適化機能について


(過去ログ 126 を表示中)

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■74749 / inTopicNo.1)  コンパイラーの最適化機能について
  
□投稿者/ min (1回)-(2015/01/27(Tue) 17:14:30)

分類:[C/C++] 


MS VC2010を使っています。

数式にsqrt(2.0f)があれば、
必ずコンパイラーに1.41421fのような具体数値に置き換えられるのでしょうか。
引用返信 編集キー/
■74755 / inTopicNo.2)  Re[1]: コンパイラーの最適化機能について
□投稿者/ 774RR (213回)-(2015/01/27(Tue) 19:21:20)
ウチに VS2010 が無いので実験してないので一般論にとどまるが・・・

特定コンパイラ+特定ソース+特定コンパイルオプションが限定できれば「そういうこともある」
一般論としては「そういうことは無い」

特に C では (C++ と違い) double sqrt(double) はあっても float sqrt(float) なる関数は無いので
sqrt(2.0f) が 1.414f になることはありえない (1.414 になることはあっても)

引用返信 編集キー/
■74761 / inTopicNo.3)  Re[2]: コンパイラーの最適化機能について
□投稿者/ 774RR (214回)-(2015/01/28(Wed) 10:36:16)
printf("%g\n", sqrt(2.0f)); // <math.h> <stdio.h> あり、に対して
// これがいいテストでないのは百も承知

i686-pc-cygwin-gcc-4.5.3 とか hppa2.0w-hp-hpux11.11-gcc-4.8.2 だと
最適化オプションに関係なく (-O0 と -O9 の両方で)
浮動小数点数リテラルを引数に取る sqrt() はコンパイル時評価され
生成される機械語上では sqrt(2.0f) が double 浮動小数点数定数値に展開された。
gcc -S -O9 sqrtest.c とか

VC++2005 では
-Od で最適化を禁ずると浮動小数点数引数をスタックに積む形式のライブラリ関数 _sqrt を呼び出す
-Ox で最適化をかけると浮動小数点数引数を FP に積む形式のライブラリ関数 __CIsqrt を呼び出す
つまりコンパイル時に定数展開する処理はしていない。
cl -Ox -FAsc sqrtest.c とか

某社の某組み込みマイコン向けCコンパイラは定数展開しなかった(詳細略)

Console.WriteLine(Math.Sqrt(2.0)); // に対して
VC#2005 では csc /o+ および csc /o- の両方でコンパイル時展開を行わない。
(ildasm で確認) csc -o+ sqrtest.cs とか。

ってことで VS2010 でどうなっているかは自分で確認してみるといい。
引用返信 編集キー/
■74762 / inTopicNo.4)  Re[3]: コンパイラーの最適化機能について
□投稿者/ min (2回)-(2015/01/28(Wed) 10:53:16)
774RR様

丁寧なご教授本当にありがとうございます。

二点質問させてください。

> -Ox で最適化をかけると浮動小数点数引数を FP に積む形式のライブラリ関数 __CIsqrt を呼び出す

ここの"FP"とは何でしょうか。



> VS2010 でどうなっているかは自分で確認してみるといい。
自分で確認する事はもっともですが、最初の質問前もそうしたかったのです。

恥ずかしながら、方法はあかりません。

皆さんどうやってコンパイル結果を確認できるのでしょうか。


どうぞ宜しくお願い致します。













No74761 (774RR さん) に返信
> printf("%g\n", sqrt(2.0f)); // <math.h> <stdio.h> あり、に対して
> // これがいいテストでないのは百も承知
>
> i686-pc-cygwin-gcc-4.5.3 とか hppa2.0w-hp-hpux11.11-gcc-4.8.2 だと
> 最適化オプションに関係なく (-O0 と -O9 の両方で)
> 浮動小数点数リテラルを引数に取る sqrt() はコンパイル時評価され
> 生成される機械語上では sqrt(2.0f) が double 浮動小数点数定数値に展開された。
> gcc -S -O9 sqrtest.c とか
>
> VC++2005 では
> -Od で最適化を禁ずると浮動小数点数引数をスタックに積む形式のライブラリ関数 _sqrt を呼び出す
> -Ox で最適化をかけると浮動小数点数引数を FP に積む形式のライブラリ関数 __CIsqrt を呼び出す
> つまりコンパイル時に定数展開する処理はしていない。
> cl -Ox -FAsc sqrtest.c とか
>
> 某社の某組み込みマイコン向けCコンパイラは定数展開しなかった(詳細略)
>
> Console.WriteLine(Math.Sqrt(2.0)); // に対して
> VC#2005 では csc /o+ および csc /o- の両方でコンパイル時展開を行わない。
> (ildasm で確認) csc -o+ sqrtest.cs とか。
>
> ってことで VS2010 でどうなっているかは自分で確認してみるといい。
引用返信 編集キー/
■74764 / inTopicNo.5)  Re[4]: コンパイラーの最適化機能について
□投稿者/ 774RR (215回)-(2015/01/28(Wed) 12:01:01)
その昔に i8087 浮動小数点数演算コプロセッサというものがあったわけだが
今の x86 アーキテクチャも i8087 の仕様を受け継いでいる。
i8087 は浮動小数点数を専用のレジスタスタックに積んだり戻したりして演算する。
FP ってのは Floating-Point (浮動小数点数) レジスタスタックを意図したつもりだった。
http://ja.wikipedia.org/wiki/Intel_8087
__CIsqrt はこの浮動小数点数レジスタスタックに引数を積んだ上で呼ぶ仕様らしい。
一方の _sqrt は通常スタックメモリ (ESP レジスタが指す) に引数を積んだ上で呼ぶ仕様らしい。
最終的な演算は浮動小数点数レジスタスタックで行われる。
_sqrt はその中で通常スタックメモリ→浮動小数点数レジスタスタックへの複写処理がある分
__CIsqrt よりも数命令だけ遅いんだろう。

Cソースに対して出力される機械語がどうなっているかは、各コンパイラのコンパイルオプションで
「アセンブラソースの出力」というのを指定してやって、そのアセンブラを人間が読むのが定番。
VS2005/2010 なら -FAcs オプションを指定すると ***.cod というファイルが出力される。
GCC なら -S オプションを指定すると ***.s というファイルが出力される。
最適化を禁止したり最大最適化を指示したりでどうアセンブラソースが変わるかを比較するんだ。

VS2005 なら (たぶん VS2010 でも同じ手順でできるはず)
Win32 コンソールアプリケーションで簡単なソースを記述し
プロジェクトの設定→ C/C++ → 出力ファイル→アセンブリの出力を /FAcs に変更
デバッグ構成でこれを実行すると最適化無効状態のアセンブラ出力が得られる
リリース構成でこれを実行すると最適化有効状態のアセンブラ出力が得られる
デバッグ構成の *.cod とリリース構成の *.cod を人間が見比べる。
# オイラはコマンドプロンプトで同じことをしたわけだけど。

x86/x64 ではサブルーチン呼び出しには CALL 命令が使われる。
call sqrt と call printf (関数名は修飾されていることがある)の2つの CALL 命令があるなら
sqrt に対してライブラリ関数呼び出しが生成されているということ。
call printf しか CALL 命令がないなら sqrt に対してライブラリ関数呼び出しが生成されていないってこと。

こんなもんでわかるかな?
引用返信 編集キー/
■74776 / inTopicNo.6)  Re[5]: コンパイラーの最適化機能について
□投稿者/ min (3回)-(2015/01/28(Wed) 17:59:32)
お世話になりました。
親切なご指導感謝の気持ちいっぱいです。

良く分かりました。


引用返信 編集キー/
■74786 / inTopicNo.7)  Re[6]: コンパイラーの最適化機能について
□投稿者/ 774RR (216回)-(2015/01/29(Thu) 09:24:38)
単にありがとうでなくて実際に試した結果を書いてくれるとうれしいな。
VS2010 の挙動をオイラも知りたいわけで(そんなところが変化しているとも思えないけど)

後から見た人のためのまとめっぽいことをしてみるテスト。

CALL sqrt が無い≠コンパイル時に定数評価された、なことに注意。
sqrt() が浮動小数点数命令にインライン展開された=演算は実行時評価している、のかもしれないし
コンパイル時定数評価されて演算自体がなくなっているのかもしれないし
その辺は前後の命令をきっちり読み解く必要がある。
先の gcc の場合は sqrt 演算自体がなくなっていることを確認済みだ。

_sqrt より __CIsqrt のほうが速いのに _sqrt がある理由は間接呼び出しのためだったりする。
関数ポインタ経由の関数呼び出しでは _sqrt しか使えない。

組み込み系マイコンではアセンブルリストを残すのはきわめて有効。
割り込み関係のバグとかタスク切り替えに関係するバグとかは ICE のトレースログが最後の頼みで
そういうのはアセンブルリストが無いと追えなかったりする。

x86/x64 くらい高度な CPU だとアセンブルリストがあまり役に立たなかったりするけどね。
マイクロ命令に翻訳した後を追いかけないと意味が無かったりとか。
キャッシュのフラッシュのタイミングがいつかで動作が変わったりとか。

まとまっているような気がしないけど解決済みにしてしまえ。
解決済み
引用返信 編集キー/
■74833 / inTopicNo.8)  Re[7]: コンパイラーの最適化機能について
□投稿者/ min (4回)-(2015/01/31(Sat) 14:06:45)

親切なご指導本当にありがとうございます。

前回も試験してから報告させていただきますと言いたかったが、
確実なタイミングを言えないので、言いませんでした。

お言葉に甘えて、近いうちに実験し、結果をご報告致します。


引用返信 編集キー/
■74855 / inTopicNo.9)  Re[8]: コンパイラーの最適化機能について
□投稿者/ 774RR (219回)-(2015/02/02(Mon) 18:40:57)
Visual Studio 2013 Community Update 4 を使う機会があったので試してみた

arch オプションの省略時解釈が SSE2 になってる
知らんかった。まあ今時のマシンはみな SSE2 使えるだろうし順当な仕様変更だろう
# ウチの開発環境が化石過ぎる・・・

x86/x64 : arch 指定 : 最適化指定 の組み合わせで膨大な量になるので全部試してないけど
さっくり調べた範囲では sqrt(double) はコンパイル時定数展開はされない様子。
# たぶん他の浮動小数点数の標準関数もみな同じだろう。
# なんとなくその理由も妄想できたりするが、単に俺の妄想なので書かないでおく

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -