[過去ログ] Visual Studio 2008 Part 22 (314レス)
前次1-
抽出解除 必死チェッカー(本家) (べ) 自ID レス栞 あぼーん

このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
267: 2018/09/17(月)01:06 ID:+dwRu2dr(1/8) AAS
>>261
だからそれは>>200と同じなんだよ。
その逆アセンブルでいうと、以下部分がメモリに出力されず、拡張倍精度で動作してるだろ。

00000281 fld qword ptr [ebp+FFFFFF14h]
00000287 fmul st,st(0)
00000289 fadd qword ptr [ebp+FFFFFF70h]
0000028f fld qword ptr [ebp+FFFFFF1Ch]
00000295 fmul st,st(0)
00000297 faddp st(1),st
00000299 fld qword ptr [ebp+FFFFFF24h]
省18
268: 2018/09/17(月)01:07 ID:+dwRu2dr(2/8) AAS
>>261(続き)
これは少なくとも「ループ回数が8の倍数である」事がコンパイラに見えないと出来ない最適化だ。
そうでなければ、例えばループ回数が6回や14回の時に、
最初の1回だけ 0299 に飛び込んで始める(頭の2回をスキップする)コードが必要になるが、
それは出てないだろ。

(そもそもこのアンローリングがx86的に意味があるのかも疑問だが)
一般的に、可変回数ループを展開すると、必ず上記の端切れ処理(キリが良くないときの処理)が必要になる。
だから「可変」だと確定しているのなら普通は展開しない。
つまり、一般的には、別関数でループ回数が引数で与えられてたら、その最適化はかからない。

今回ヒットするデータが偶々16回ループだっただけで、
省8
286
(1): 2018/09/17(月)10:25 ID:+dwRu2dr(3/8) AAS
>>191がコンソール起動とIDE起動で挙動が異なる理由は分かりました。
ありがとう。

結論はつまり以下だ。
> JIT の最適化とデバッグ(抜粋)
> マネージ アプリケーションをデバッグするとき、Visual Studio では、既定で、
> ジャスト イン タイム (JIT: Just-In-Time) コードの最適化が省略されています。
> 最適化されたコードをデバッグするのは困難であるため、
> 最適化されたコードで発生するバグが、非最適化バージョンでは再現しないときにのみお勧めします。
> JIT 最適化は、Visual Studio の [モジュールの読み込み中に JIT 最適化を抑制する] オプションで制御されます。
> 実行中のプロセスにアタッチする場合、既に読み込まれ、JIT でコンパイルされ、
省4
287: 2018/09/17(月)10:25 ID:+dwRu2dr(4/8) AAS
その他諸々、話を整理すると、以下となる。(ソースは>>191参照)
1. managedコードではMSILが出力され、x86コードは含まれていない。
2. 起動時、MSILはJITされ、x86コードに落とされる。
3. このため、mainの1行目でブレークポイントで止め、calc_norm_and_regulateの逆アセンブルを見ようとしても、
 IDE上で「逆アセンブルを表示できません。式がまだネイティブ マシン コードに翻訳されていません。」と出る。
 これはmainの1行目に System::Diagnostics::Debugger::Launch(); を入れたときも同様。
4. そしてこのJITに関して、上記IDE中の 『[モジュールの読み込み中に JIT 最適化を抑制する] オプション』 が効いてくる。
 規定ではオフ、つまり、ReleaseビルドでもIDE起動ならJIT最適化は抑制される。
 これがfld/fmul/fadd/fstpのループコードになる理由。
 これをオンにすれば、確かにReleaseビルドIDE起動でも、
省12
292
(1): 2018/09/17(月)10:52 ID:+dwRu2dr(5/8) AAS
>>288
お前は相変わらず理解してないな。

80bit(拡張倍精度)と64bit(倍精度)の演算で桁落ちが異なり、結果が異なるのは当然なんだよ。
問題は同じバイナリの癖に何故起動方法によって異なるのか?だったんだ。

理由はMSILだからだ。
MSILはCLR上でJITされ、x86コードに落とされる。
このときにJIT最適化がかかれば、拡張倍精度(を保ったまま)のコードになるし、
最適化がかからず毎回メモリに書き戻していれば、倍精度のコードになる。
.NETにおける同一バイナリってのは、同一MSILという意味であって、同一x86機械語という意味ではない。
だから、確かに同一バイナリを掴んでいたが、起動方法によって結果が異なっていたんだよ。
省9
293: 2018/09/17(月)10:54 ID:+dwRu2dr(6/8) AAS
× fprint
○ printf
まあ、分かると思いますが
301
(1): 2018/09/17(月)17:03 ID:+dwRu2dr(7/8) AAS
>>300
はい。よく壊れます。
> [C++] There is an issue with the .ncb file
> Close the solution.
> Delete the . ncb file.
> Reopen the solution.
> Reopening the solution creates a new . ncb file.
> 外部リンク:msdn.microsoft.com
303: 2018/09/17(月)18:30 ID:+dwRu2dr(8/8) AAS
さて俺の本番コード、以下のようだ。
疑問は解消した。協力してくれた皆様ありがとう。

◎:拡張倍精度、○:倍精度、として、(ソースは>>191参照)
・Releaseビルドをコマンドプロンプトから起動→◎積和、◎平方根
・Debugビルドをコマンドプロンプトから起動→◎積和、○平方根
・IDEから起動→○積和、○平方根

これで3種類出来上がってた。
(なお、>>166内バイナリをアタッチした際の「AまたはC」は、「AまたはB」の間違い)
そしてIDE上で『[モジュールの読み込み中に JIT 最適化を抑制する]』を変更すると、
確かにRelease/Debugの2種類に絞れる。
省19
前次1-
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル

ぬこの手 ぬこTOP 0.219s*