[過去ログ]
Visual Studio 2008 Part 22 (314レス)
Visual Studio 2008 Part 22 http://mevius.5ch.net/test/read.cgi/tech/1413180800/
上
下
前
次
1-
新
通常表示
512バイト分割
レス栞
このスレッドは過去ログ倉庫に格納されています。
次スレ検索
歴削→次スレ
栞削→次スレ
過去ログメニュー
181: デフォルトの名無しさん [sage] 2018/09/15(土) 14:05:09.61 ID:heijdb7v Intel® 64 and IA-32 Architectures Software Developer’s Manual [Vol 1] 11.6.8 Compatibility of SIMD and x87 FPU Floating-Point Data Types SSE and SSE2 extensions operate on the same single-precision and double-precision floating-point data types that the x87 FPU operates on. However, when operating on these data types, the SSE and SSE2 extensions operate on them in their native format (single-precision or double-precision), in contrast to the x87 FPU which extends them to double extended-precision floating-point format to perform computations and then rounds the result back to a single-precision or double-precision format before writing results to memory. Because the x87 FPU operates on a higher precision format and then rounds the result to a lower precision format, it may return a slightly different result when performing the same operation on the same single-precision or double-precision floating-point values than is returned by the SSE and SSE2 extensions. The difference occurs only in the least-significant bits of the significand. http://mevius.5ch.net/test/read.cgi/tech/1413180800/181
182: デフォルトの名無しさん [sage] 2018/09/15(土) 14:14:58.92 ID:heijdb7v >>181 書いてある意味は、 「SSEやSSE2だと、float(32BIT)やdouble(64BIT)のまま計算するが、x87 fpuだと、もっと高い精度であるところの 『double extended-precision floating-point format(拡張倍精度浮動小数点フォーマット:80BIT)』 で計算を実行して、丸めてから、floatやdoubleに戻す。 そのため、SSE/SSE2 と x87 fpuでは結果が変わることがある。 しかし、その場合でも結果の違いは、仮数部の LSB (最も価値の小さいBIT)の1BITにだけ現れる。」 というような事。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/182
183: デフォルトの名無しさん [sage] 2018/09/15(土) 16:09:28.75 ID:aC3C7hdp 揚げ足取りだけどLSBを「最も価値が小さい」って直訳はいかがなものかなw 普通に最下位ビットじゃないの? ところで > the least-significant bits これ何で複数形なのかね http://mevius.5ch.net/test/read.cgi/tech/1413180800/183
184: デフォルトの名無しさん [] 2018/09/15(土) 16:14:15.89 ID:AVfR6YnT 2の0乗だから実際価値が低い 上はMVBで http://mevius.5ch.net/test/read.cgi/tech/1413180800/184
185: デフォルトの名無しさん [sage] 2018/09/15(土) 17:07:56.98 ID:UR1d6CKz >>182 ありがとう。 ただ一応それは知ってて、その上で、IDEの環境設定等を疑っている。 >>177 とはいえ地道に辿って、同様の再現コードを作ることに成功しそうだ。 もう少し調べて、多分今晩か明日午前中に上げる。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/185
186: デフォルトの名無しさん [sage] 2018/09/15(土) 17:12:32.47 ID:heijdb7v >>183 「The difference occurs only in the least-significant bits of the significand.」 これは、SSE の場合の LSB と、x87 FPU の場合の FPU の2種類を頭の中に想定していると思われる。 SSE: a1 = 1.xxxxxxxxz * 10^b x87 : a2 = 1.yyyyyyyyw * 10^c つまり、LSB は、↑のように、z と w で、2つあるので、LSBs という英語になる。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/186
187: デフォルトの名無しさん [sage] 2018/09/15(土) 17:15:04.14 ID:heijdb7v 誤:これは、SSE の場合の LSB と、x87 FPU の場合の FPU の2種類を 正:これは、SSE の場合の LSB と、x87 FPU の場合の 2種類を http://mevius.5ch.net/test/read.cgi/tech/1413180800/187
188: デフォルトの名無しさん [sage] 2018/09/15(土) 17:18:55.19 ID:heijdb7v >>183 >揚げ足取りだけどLSBを「最も価値が小さい」って直訳はいかがなものかなw >普通に最下位ビットじゃないの? 整数の場合は、「最下位ビット」というと、本当にBITの位置が一番右にあるようなイメージもある。 一方、浮動小数点数の場合は、右にあるとかより、仮数部において、一番価値の小さいビット、というニュアンスを使えたかった。 IEEEでは、それは確かに一番右にあるビットであって、マシン語レベルの表現では、BIT0ではあるのだが。 ニュアンス的に。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/188
189: デフォルトの名無しさん [sage] 2018/09/15(土) 17:29:56.92 ID:aC3C7hdp >>186 それは俺も思ったけど、それならsignificandの方も複数じゃないとおかしいような... http://mevius.5ch.net/test/read.cgi/tech/1413180800/189
190: デフォルトの名無しさん [sage] 2018/09/15(土) 20:35:40.44 ID:UR1d6CKz 同様の症状を再現出来るようになったので上げる。 完全再現は出来てないが、使い物にはなるはず。興味がある人はよろしく。 症状: 単独で起動した場合と、IDEから起動した場合で、結果が異なる。 環境: VS++2008ExpressEdition 再現方法: 1. 新規プロジェクトを作成。(CLRコンソールアプリケーション。オプション等は全てデフォのまま) 2. mainを以下ソースと差し替える。 3. Releaseビルドで実行する。(Debugビルドでは再現しなかったので注意) 結果: 0.000000, 0x1ff68ddfb62221dd (IDEからの起動(F5)) 0.000000, 0x1ff68ddfb62221de (コマンドプロンプトからの起動) 最後の2bitが異なる。(誤差は1bit) 備考: 俺が遭遇しているのとはやや異なる。(俺の場合、Debugビルドでもこれが発生する) この再現状況だと、単に 「DebugとReleaseでバイナリが異なり、 IDEから起動した場合は常にDebugバイナリを掴んでいるだけでは?」 とも取れるが、こちらで確認した限りはちゃんとReleaseバイナリを掴んでいる。 理由は、 1. Debug/Releaseの両方のバイナリがない状態で実行した場合、 自動的に作成されるのはReleaseバイナリ。(当然だが) 結果は****ddとなる。(ブレークポイント等で止めて確認する) 2. そのReleaseバイナリをコマンドプロンプトから起動すると、****deの結果が得られる。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/190
191: デフォルトの名無しさん [sage] 2018/09/15(土) 20:37:06.43 ID:UR1d6CKz ソース: #include "stdafx.h" #include <math.h> using namespace System; template<typename T> static double calc_norm_and_regulate(int num, T* r, bool regulate){ // <float> for debug. double norm = 0; for (int i=0;i<num;i++) norm += (double)r[i] * (double)r[i]; norm = sqrt(norm); if (regulate) for (int i=0;i<num;i++) r[i] = (T)(r[i]/norm); return norm; } int main(array<System::String ^> ^args) { int count = 16; __int64 inputs_hex[16] = { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1fedb1530240aa54, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1ff0af0d95025bc3, 0x1fc9353df6af376b, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}; double* inputs = (double*)inputs_hex; double norm = calc_norm_and_regulate(count, inputs, false); Console::Write(String::Format("{0:F6}, 0x{1:x16}\r\n",norm, *(__int64*)&norm)); // Release build // 0.000000, 0x1ff68ddfb62221dd from IDE // 0.000000, 0x1ff68ddfb62221de from command prompt return 0; } http://mevius.5ch.net/test/read.cgi/tech/1413180800/191
192: デフォルトの名無しさん [sage] 2018/09/15(土) 20:42:48.06 ID:UR1d6CKz オプション等(コマンドライン):(全てデフォのままのはずだが一応) C/C++: /GL /D "WIN32" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /FD /EHa /MD /Yu"stdafx.h" /Fp"Release\test_floating_error4.pch" /Fo"Release\\" /Fd"Release\vc90.pdb" /W3 /nologo /c /Zi /clr /TP /errorReport:prompt /FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll" /FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll" /FU "c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.XML.dll" リンカ: /OUT:"MYPATH\test_floating_error4\Release\test_floating_error4.exe" /INCREMENTAL:NO /NOLOGO /MANIFEST /MANIFESTFILE:"Release\test_floating_error4.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"MYPATH\test_floating_error4\Release\test_floating_error4.pdb" /LTCG /DYNAMICBASE /FIXED:No /NXCOMPAT /MACHINE:X86 /ERRORREPORT:PROMPT パスは$MYPATHと書き換えた。また、投稿の為に適宜改行を入れた。 このプロジェクト名は見れば分かるとおりtest_floating_error4。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/192
193: デフォルトの名無しさん [sage] 2018/09/15(土) 20:43:03.84 ID:UR1d6CKz 備考2: なおこの方法で見える calc_norm_and_regulate 関数の『逆アセンブル』結果は 俺の環境での物とコールアドレス以外は一致していることを確認している。 一応、diff結果は以下。 8c8 < 0000000c cmp dword ptr ds:[00752E14h],0 --- > 0000000c cmp dword ptr ds:[007D2E14h],0 10c10 < 00000015 call 676F58B9 --- > 00000015 call 683C58B9 44c44 < 0000006a call FF0455E8 --- > 0000006a call FFD955E8 http://mevius.5ch.net/test/read.cgi/tech/1413180800/193
194: デフォルトの名無しさん [sage] 2018/09/16(日) 02:47:43.28 ID:wIV2HUNW >>190 C++/CLR では、.Net を使っているから、起動方法が違うだけでも、 fpu control word の値や、使うCPU命令がx87 FPUなのか、SSE なのかが違ってくる可能性があるかもしれない。 fpu control word は、main()関数に入る前の start up codeの中で 初期化される。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/194
195: デフォルトの名無しさん [sage] 2018/09/16(日) 03:19:36.22 ID:wIV2HUNW >>191 // Release build // 0.000000, 0x1ff68ddfb62221dd from IDE // 0.000000, 0x1ff68ddfb62221de from command prompt それにしても、随分小さな値だね。ちなみに、浮動小数点表示 の場合の有効数字の桁数を上げたら、どのようになる? 1.xxxe-yy 表示にして。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/195
196: デフォルトの名無しさん [sage] 2018/09/16(日) 03:40:33.66 ID:wIV2HUNW >>191 試しに、ソースの冒頭に #include <stdio.h> を追加してから、 Console::Write(String::Format("{0:F6}, 0x{1:x16}\r\n",norm, *(__int64*)&norm)); の部分を、 printf( "%30.30e, 0x%016X\n", norm, *(__int64*)&norm) ); としてみるとどうなる? http://mevius.5ch.net/test/read.cgi/tech/1413180800/196
197: デフォルトの名無しさん [sage] 2018/09/16(日) 03:42:01.82 ID:wIV2HUNW >>196 誤: printf( "%30.30e, 0x%016X\n", norm, *(__int64*)&norm) ); 正: printf( "%30.30e, 0x%016X\n", norm, *(__int64*)&norm ); http://mevius.5ch.net/test/read.cgi/tech/1413180800/197
198: デフォルトの名無しさん [] 2018/09/16(日) 07:27:22.50 ID:SOVIz+sV > 0x1ff68ddfb62221dd(Debug) > 0x1ff68ddfb62221de(Release) VS 2010 VC++ Express でも再現した http://mevius.5ch.net/test/read.cgi/tech/1413180800/198
199: デフォルトの名無しさん [] 2018/09/16(日) 07:38:10.70 ID:SOVIz+sV ↓このループを抜けたあと、すでにReleaseビルドとDebugビルドでは normの値に差異が発生してることが確認できた for (int i=0;i<num;i++) norm += (double)r[i] * (double)r[i]; ↓この下に(ループ内に)fprintf文を入れるだけで ReleaseビルドとDebugビルドが同じ実行結果になることが確認できた norm += (double)r[i] * (double)r[i]; とりあえずまずこれだけは分かったから 低学歴知恵遅れが書いたウンココードの問題箇所を限定する http://mevius.5ch.net/test/read.cgi/tech/1413180800/199
200: デフォルトの名無しさん [] 2018/09/16(日) 07:51:03.41 ID:SOVIz+sV ?-1 デフォルト設定(Release) 【コード】 #include "stdafx.h" #include <stdio.h> #include <stdint.h> #include <math.h> int main(array<System::String ^> ^args) { __int64 inputs_hex[16] = { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1fedb1530240aa54, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1ff0af0d95025bc3, 0x1fc9353df6af376b, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }; double* r = (double*)inputs_hex; double norm = 0; for (int i = 0; i < 16; i++) { norm += (double)r[i] * (double)r[i]; // fprintf(stdout, "[1]0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm); } fprintf(stdout, "0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm); return 0; } http://mevius.5ch.net/test/read.cgi/tech/1413180800/200
201: デフォルトの名無しさん [] 2018/09/16(日) 07:51:56.62 ID:SOVIz+sV ?-1 デフォルト設定(Release) ↓このコードの逆アセンブルコード https://ideone.com/Ryyxkl 【実行結果】 0x0007F2C44DFFF8F2:1.1053482540585106e-308 http://mevius.5ch.net/test/read.cgi/tech/1413180800/201
202: デフォルトの名無しさん [] 2018/09/16(日) 07:53:20.79 ID:SOVIz+sV ?-2 デフォルト設定(Release) #include "stdafx.h" #include <stdio.h> #include <stdint.h> #include <math.h> int main(array<System::String ^> ^args) { __int64 inputs_hex[16] = { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1fedb1530240aa54, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x1ff0af0d95025bc3, 0x1fc9353df6af376b, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }; double* r = (double*)inputs_hex; double norm = 0; for (int i = 0; i < 16; i++) { norm += (double)r[i] * (double)r[i]; fprintf(stdout, "[1]0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm); } fprintf(stdout, "0x%016llX:%.19lg\n", *(uint64_t*)&norm, norm); return 0; } http://mevius.5ch.net/test/read.cgi/tech/1413180800/202
203: デフォルトの名無しさん [] 2018/09/16(日) 08:02:12.99 ID:SOVIz+sV ?-2 デフォルト設定(Release) ↓このコードの逆アセンブルコード https://ideone.com/4j12ib 【実行結果】 ↓実行結果を書き込めないからこっちに書き込んどいた https://ideone.com/gOqtki 0x0007F2C44DFFF8F1:1.1053482540585101e-308 http://mevius.5ch.net/test/read.cgi/tech/1413180800/203
204: デフォルトの名無しさん [] 2018/09/16(日) 08:05:50.92 ID:SOVIz+sV ?-1 最適化無効 (/Od)(Release) ※ コードは?-1(>>200)と同じ ↓このコードの逆アセンブルコード https://ideone.com/cONCAx 【実行結果】 0x0007F2C44DFFF8F1:1.1053482540585101e-308 http://mevius.5ch.net/test/read.cgi/tech/1413180800/204
205: デフォルトの名無しさん [] 2018/09/16(日) 08:09:59.78 ID:SOVIz+sV ?-2 最適化無効 (/Od)(Release) ※ コードは?-2(>>202)と同じ ↓このコードの逆アセンブルコード https://ideone.com/kuRt3w 【実行結果】 ※ ?-2(>>203)と同じ 0x0007F2C44DFFF8F1:1.1053482540585101e-308 http://mevius.5ch.net/test/read.cgi/tech/1413180800/205
206: デフォルトの名無しさん [] 2018/09/16(日) 08:20:27.67 ID:SOVIz+sV ?-1、?-2の逆アセンブルの出力結果を比較すると原型をとどめてないぐらいグチョグチョに違う(最適化のせいと考えられる) ?-1、?-2の逆アセンブルの出力結果を比較すると差異はほとんどない(?は両方ともまったく最適化されてないから当然) ?-1と?-1の逆アセンブルの出力結果を比較すると原型をとどめてないぐらいグチョグチョに違う(?-1のコード(>>200)ははげしくウンコ最適化されてると考えられる) ?-2と?-2の逆アセンブルの出力結果を比較すると差異はほとんどない(?-2のコード(>>202)はあまり最適化されてないと考えられる) はっきりいって、これ以上見る気もしないしテキトーだが ウンコみたいな最適化で演算の順序が入れ替わったせいで、誤差が発生しているものと考えられる http://mevius.5ch.net/test/read.cgi/tech/1413180800/206
207: デフォルトの名無しさん [sage] 2018/09/16(日) 08:28:37.25 ID:zL1WUjLu >>198以降、 すまん、入れ替わりになるかもしれんが後で確認する。 まず>>194その他について回答する。 >>194 SSEは /arch:SSE または /arch:SSE2 でないと出ないことになっており、勿論設定はしていない。 また、逆アセンブル結果では x87 命令のみであるのも確認している。 ただ今回の問題は、本当にReleaseビルドのバイナリを逆アセンブルしているか怪しい事だが。 >>195 小さい値なのは偶々だ。 辿って行ってそれが1回目にヒットする入力データだっただけのこと。 >>196 .NETの書式指定はググり難いが以下。 https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings 概ねprintfと同じで、自動的にやってくれるのが増えている。 30桁欲しければ以下。 Console::Write(String::Format("{0:E6}, {0:E30}\r\n",norm)); // 出力は 1.051355E-154, 1.051355436595307800000000000000E-154 なおdoubleは16桁な。(15.9=53*log(10)2) ただ当たり前だが、書式を変えたところで計算結果は変わらないし、 精度の問題には関係ない。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/207
208: デフォルトの名無しさん [sage] 2018/09/16(日) 08:29:03.14 ID:zL1WUjLu >>194 FPU control registor については何故か安定した結果を得られていない。 インラインアセンブラは以下の通りで、 #pragma unmanaged inline void fpu_getcw(unsigned short* cw) { __asm{ fnstcw [cw]; } } #pragma managed これを norm = calc_norm_and_regulate( ... ) の直前/直後に配置して読み出し、 同様にコンソール出力すると、以下となる。 また、IDEで起動した場合は、「レジスタ」で見れる。 なお定義は以下の通り。 [9:8]に対し、 0x00 : 単精度(24bit) 0x01 : reserved 0x10 : 倍精度(53bit) 0x11 : 拡張倍精度(64bit) [11:10]に対し 0x00 : 最近値 0x01 : 切り捨て 0x10 : 切り上げ 0x11 : 0方向への切り捨て http://mevius.5ch.net/test/read.cgi/tech/1413180800/208
209: デフォルトの名無しさん [sage] 2018/09/16(日) 08:29:57.53 ID:zL1WUjLu >>194 直後のみに配置: 0x027F (倍精度) = Debug(IDE起動)のIDE内表示、Release(IDE起動)のIDE内表示、 0x03a5 (拡張倍精度) = Debug(IDE起動)、Release(IDE起動)、 0x3fdc (拡張倍精度) = Debug(コマンドプロンプト)、 0xf280, 0xf290, 0xf160, 0xf010等、不安定 = Release(コマンドプロンプト) 直前のみに配置: 直後のみと同じ結果。(つまり『何故か』安定している) Release(コマンドプロンプト)は不安定なのも同じ。 直前と直後に配置: 直前側は当然不安定になる。 直後側は「直後のみ」の結果と同じ。(Release(コマンドプロンプト)は不安定なのも同じ) 雰囲気からすると、IDE内表示は当てにならず、 命令自体は rdtsc と同じで非同期に実行されている雰囲気だが、 rdtsc命令の注意書きにある「シリアル化命令ではない」という但し書きが無く、状況は不明。 正直、正しく読み出せているか怪しい。(あてにならない) これらから推測すると、暫定的には以下。 拡張倍精度 = Debug(IDE起動)、Release(IDE起動)、Debug(コマンドプロンプト)、 不明 = Release(コマンドプロンプト) 以上が>>194その他に対する回答。 これから>>198その他について確認する。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/209
210: デフォルトの名無しさん [sage] 2018/09/16(日) 12:52:37.56 ID:haV9TZ8e >>209 興味深い結果だ。 http://mevius.5ch.net/test/read.cgi/tech/1413180800/210
メモ帳
(0/65535文字)
上
下
前
次
1-
新
書
関
写
板
覧
索
設
栞
歴
あと 104 レスあります
スレ情報
赤レス抽出
画像レス抽出
歴の未読スレ
AAサムネイル
Google検索
Wikipedia
ぬこの手
ぬこTOP
0.018s