[過去ログ] Visual Studio 2008 Part 22 (314レス)
1-

このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
251
(2): 240 2018/09/16(日)21:43 ID:/oSJzlqn(2/5) AAS
.netの場合、デバッガ配下では(デバッグのため)違うコードを実行しているような気がする。
デバッガの逆アセンブル表示とかasm出力はあまり当てにならないような気もする。
ループ部分だけど、レジスタのみで処理するか、メモリを使用するかで精度が変わるのかも。
そもそも、どっちが正しいのかよくわからんけど...
ループ部分の関数を#pragma unmanagedすると結果が変わるでそれが正しいのかも。
252
(4): 240 2018/09/16(日)21:43 ID:/oSJzlqn(3/5) AAS
static版
0000000e 33 C0 xor eax,eax
00000010 85 F6 test esi,esi
00000012 7E 16 jle 0000002A
00000014 DD 04 C7 fld qword ptr [edi+eax*8]
00000017 DC C8 fmul st(0),st
00000019 DC 05 00 30 CC 00 fadd qword ptr ds:[00CC3000h]
0000001f DD 1D 00 30 CC 00 fstp qword ptr ds:[00CC3000h]
00000025 40 inc eax
00000026 3B C6 cmp eax,esi
省13
253
(1): 2018/09/16(日)22:27 ID:zL1WUjLu(23/27) AAS
>>251
とりあえず落ち着け。一つずつ行こう。

> ループ部分の関数を#pragma unmanagedすると結果が変わるでそれが正しいのかも。
こちらでも確認した。
calc_norm_and_regulateをunmanaged関数にすると、違いはなくなる。
(Releaseビルドの`をコマンドプロンプトで起動した際にも、****ddの結果となる)

ただしこちらの逆アセンブル結果は以下だ。(fld/fmul/fadd/fstpであることに注意)
for (int i=0;i<num;i++) norm += (double)r[i] * (double)r[i];
0007272C C7 45 F4 00 00 00 00 mov dword ptr [i],0
00072733 EB 09 jmp `anonymous namespace'::calc_norm_and_regulate<double>+1Eh (7273Eh)
省15
254: 2018/09/16(日)22:33 ID:zL1WUjLu(24/27) AAS
>>252
そちらの逆アセンブルは以下の違いが出てるだろ。
static版: fld/fmul/fadd/fstp
非static版: fld/fmul/faddp (fstpが無い)
この非static版の場合、拡張倍精度(80bit)で演算されるから精度が高いことになり、
static版との演算結果に違いが出るのも仕様通りなんだよ。(これは>>200と同じ間違い)

一応、fstpにも80bit版はあって、Intelのマニュアルによると以下。
> オペコード命令説明
> D9 /2 FST m32fp ST(0) をm32fp にコピーする。
> DD /2 FST m64fp ST(0) をm64fp にコピーする。
省14
255: 2018/09/16(日)22:34 ID:zL1WUjLu(25/27) AAS
>>252
> .netの場合、デバッガ配下では(デバッグのため)違うコードを実行しているような気がする。
> デバッガの逆アセンブル表示とかasm出力はあまり当てにならないような気もする。
これは俺も相当疑っているのだが、今のところ尻尾を掴めない。
ILspyだっけ?外部の逆アセンブルツール使えばチェック出来るのかな?

いずれにしても、>>251の指摘
・unmanagedにすれば直る
のも事実だし、逆アセンブルを見る限り、これを説明出来る理由もないのも事実。
256
(1): 240 2018/09/16(日)23:13 ID:/oSJzlqn(4/5) AAS
> だから>>252の場合の誤差なら、仕様通りなんだよ。(片方が倍精度、もう片方は拡張倍精度)
そうなの? これが仕様通りならstatic版での違いは仕様通りということになる。
252はRelease版をコンソールで実行したときの逆アセンブル結果。
よって、Release版をコンソールで実行したときのみ(たまたま)レジスタ(80ビット)での演算になるので、
計算結果が変わるのはやむを得ないという結論になるのだが...

ちなみに、235はDebugモードでコンパイルし、デバッガ配下の逆アセンブル結果でしょ。
257
(1): 2018/09/16(日)23:24 ID:zL1WUjLu(26/27) AAS
>>256
> 252はRelease版をコンソールで実行したときの逆アセンブル結果。
それはどうやって得たの?俺はそれが出来ないから困ってる。

> ちなみに、235はDebugモードでコンパイルし、デバッガ配下の逆アセンブル結果でしょ。
235は、IDE上でReleaseモードでF5で起動し、ブレークポイントを当てて止めて逆アセンブルした結果。
俺が貼ってる逆アセンブル結果は全てこの方法で、IDEで表示されているもの。
だからIDEの表示がおかしかったら話が全部おかしくなる。

君がIDEから独立して逆アセンブル出来ているのなら、その方法を知りたい。
こちらでも試す。

なおILSpy、グダグダ言わずに試してみたが、
省4
258
(1): 240 2018/09/16(日)23:35 ID:/oSJzlqn(5/5) AAS
>> 252はRelease版をコンソールで実行したときの逆アセンブル結果。
>それはどうやって得たの?俺はそれが出来ないから困ってる。
calc_norm_and_regulateの次の行に
System::Diagnostics::Debugger::Launch();
を入れてコンソールから実行すると just in time デバッグできるので、デバッガを選んだ後、
Visual Studioの 呼び出し履歴から calc_norm_and_regulate を探して移動する

>> ちなみに、235はDebugモードでコンパイルし、デバッガ配下の逆アセンブル結果でしょ。
>235は、IDE上でReleaseモードでF5で起動し、ブレークポイントを当てて止めて逆アセンブルした結果。

あれ? だとすると最適化していないのでは?
こちらの結果と違うのだが。
259
(1): 2018/09/16(日)23:49 ID:SOVIz+sV(10/15) AAS
AA省
260
(1): 2018/09/16(日)23:50 ID:SOVIz+sV(11/15) AAS
AA省
261
(3): 2018/09/16(日)23:51 ID:SOVIz+sV(12/15) AAS
?-1 デフォルト設定(Release) 【実行結果】

↓このコードの逆アセンブルコード
外部リンク:ideone.com

[1]0x0007F2C44DFFF8F2:1.1053482540585106e-308
[2]0x1FF68DDFB62221DE:1.051355436595308e-154
262
(1): 2018/09/16(日)23:54 ID:SOVIz+sV(13/15) AAS
AA省
263
(1): 2018/09/16(日)23:54 ID:SOVIz+sV(14/15) AAS
AA省
264
(1): 2018/09/16(日)23:56 ID:SOVIz+sV(15/15) AAS
?-2 デフォルト設定(Release) 【実行結果】

↓このコードの逆アセンブルコード
外部リンク:ideone.com

↓実行結果を書き込めないからこっちに書き込んどいた
外部リンク:ideone.com

[1]0x0007F2C44DFFF8F1:1.1053482540585101e-308
[2]0x1FF68DDFB62221DD:1.0513554365953078e-154

以上だ
265
(1): 2018/09/16(日)23:58 ID:zL1WUjLu(27/27) AAS
>>258
おお、そのやり方は知らなかった。大変助かった。ありがとう。
で、結果だが、>>252とは微妙に違うが、確かに拡張倍精度で計算されている。
逆アセンブル結果は、以下。

0000000e D9 EE fldz
for (int i=0;i<num;i++) norm += (double)r[i] * (double)r[i];
00000010 33 C9 xor ecx,ecx
00000012 EB 01 jmp 00000015
00000014 41 inc ecx
00000015 3B CE cmp ecx,esi
省16
266: 2018/09/17(月)00:49 ID:gBxGzBbQ(1) AAS
>>265
ideとconsoleで微妙に違うバージョンのvcruntimeがロードされてるとか?
process monitorで何が実行されて何がロードされてるか調べるとか?
あとはwindbgから起動したら、ideとconsoleのどちらの結果と一致するのか気になる。
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
269
(1): 247 2018/09/17(月)01:12 ID:yaPtorLJ(1/7) AAS
今、戻った。

席を離れて思ったが、多分、C++/CLI の場合、IDEでコンパイル後、
exeファイルになっても、unmanaged コード部分以外は、本質的には
.NETの共通中間言語(CIL、MSIL)になるだけで、x86のマシン語には
なってないと思う。一方、昔ながらの本当のC++では、exeの中身は、
本質的には、x86のマシン語が入っていた。

C++/CLIの場合、作成されたexeは、起動時に、中間言語がx86の
マシン語に直されてから実行される。その際、最適化の関係で、
どう直されるかが必ずしも一定していない。だから、IDEからの起動と、
コマンドラインからの起動で異なったx86命令に直されてしまう
省10
270: 243=269 2018/09/17(月)01:14 ID:yaPtorLJ(2/7) AAS
>>269
名前欄は、「247」ではなく「243」の間違いだった。
271: 2018/09/17(月)01:24 ID:yaPtorLJ(3/7) AAS
>>257
>なおILSpy、グダグダ言わずに試してみたが、
>当たり前だがmanaged code だとILが出る(x86ではない)ので、
>俺って根本的に間違ってたかも?
>今までx86のアセンブラで議論してたけど、これって .NET アプリには同梱されていないというオチ?

やはり、managed code部分は、x86命令では無く、ILにコンパイルされていて、
普通のC++とは違ってたんだ。
272: 2018/09/17(月)01:30 ID:yaPtorLJ(4/7) AAS
>calc_norm_and_regulateをunmanaged関数にすると、違いはなくなる。
>(Releaseビルドの`をコマンドプロンプトで起動した際にも、****ddの結果となる)

やはり。
unmanaged関数の場合は、CIL(MSIL)ではなく、exeの段階で既に
x86マシン語に直されたものが格納されるんだろう。だとすると、起動方法に
関係なく、少なくともその部分に関しては、x87 fpu命令の使われ方が
全く同じになる。callしたsqrt()関数の中は除いて。
273
(1): 2018/09/17(月)01:37 ID:dj7qSZnZ(1/17) AAS
>>259-260のコードも>>262-263
も同じ条件でデフォルトでコンパイルしてる
コレは間違いない

一行コメントはずしてコンパイルしなおすだけだからな

で、>>261>>264みたいな結果になる
>>264の実行結果はDebugビルドとまったく同じになる
そのまんま
274: 2018/09/17(月)02:03 ID:yaPtorLJ(5/7) AAS
はっきり書いてある。managed code は、起動時にJITコンパイルされる。
だから、どんなマシン語に置き換わるかが、コンパイルしただけでは
まだ完全には決定されてない。

外部リンク:en.wikipedia.org

Drawbacks include slower startup speed (the managed code must be JIT
compiled by the VM) and generally increased use of system resources
on any machine that is executing the code.

managed code は、VMによって、JIT コンパイルされないといけないので、
起動速度が遅くなり、かつ、一般的に、システム・リソースの使用が増える。
275: 2018/09/17(月)02:49 ID:dj7qSZnZ(2/17) AAS
普通のコンソールアプリケーション(CLRじゃないほう)でも
同じコードで普通にまったく同じように再現するワケだが

ホントなキミラはなにを頭悪いことばっかりいってんの?
実行結果だけははっといてやるが
276
(1): 2018/09/17(月)02:50 ID:dj7qSZnZ(3/17) AAS
AA省
277
(1): 2018/09/17(月)02:50 ID:dj7qSZnZ(4/17) AAS
AA省
278
(1): 2018/09/17(月)02:51 ID:dj7qSZnZ(5/17) AAS
?-1 デフォルト設定(Release) 【実行結果】

↓このコードの逆アセンブルコード
外部リンク:ideone.com

[1]0x0007F2C44DFFF8F2:1.1053482540585106e-308
[2]0x1FF68DDFB62221DE:1.051355436595308e-154
279
(1): 2018/09/17(月)02:51 ID:dj7qSZnZ(6/17) AAS
AA省
280
(1): 2018/09/17(月)02:52 ID:dj7qSZnZ(7/17) AAS
AA省
1-
あと 34 レスあります
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル

ぬこの手 ぬこTOP 0.038s