我在此:
#include <stdio.h>
#include <stdlib.h>
typedef long double ldbl;
ldbl x[1<<20];
void hexdump(void* p, int N) {
for(int i=0; i<N; i++) printf("%02X", ((unsigned char*)p)[i]);
}
int main(int argc, char** argv) {
printf("sizeof(long double)=%i\n", sizeof(ldbl));
if(argc<2) return 1;
int i;
ldbl a = ldbl(1)/atoi(argv[1]);
for(i=0; i<sizeof(x)/sizeof(x[0]); i++) x[i]=a;
while(1) {
for(i=0; i<sizeof(x)/sizeof(x[0]); i++) if(x[i]!=a) {
hexdump(&a, sizeof(a));
printf(" ");
hexdump(&x[i], sizeof(x[i]));
printf("\n");
}
}
}
使用/ Qlong_double編譯IntelC,使其產生這樣的:
;;; for(i=0; i<sizeof(x)/sizeof(x[0]); i++) if(x[i]!=a) {
xor ebx, ebx ;25.10
; LOE ebx f1
.B1.9: ; Preds .B1.19 .B1.8
mov esi, ebx ;25.47
shl esi, 4 ;25.47
fld TBYTE PTR [[email protected]@3PA_TA+esi] ;25.51
fucomp ;25.57
fnstsw ax ;25.57
sahf ;25.57
jp .B1.10 ; Prob 0% ;25.57
je .B1.19 ; Prob 79% ;25.57
[...]
.B1.19: ; Preds .B1.18 .B1.9
inc ebx ;25.41
cmp ebx, 1048576 ;25.17
jb .B1.9 ; Prob 82% ;25.17
,並開始10個實例具有不同的 「種子」。正如你所看到的,它將來自內存的10個字節長的雙精度浮點數與FPU堆棧中的一個進行比較,所以在 操作系統不能保持完全精度的情況下,我們肯定會看到一個錯誤。 嗯,它們仍然運行時沒有檢測到任何東西......這真的不是真的 令人驚訝的,因爲x86有一次保存/恢復整個FPU狀態的命令,無論如何一個操作系統不會保持完全精度完全破碎。
因此,無論它的一些獨特的OS/CPU /編譯器,或不同的比較結果 在節目中,例如,在程序改變的東西,重新編譯它,或者它的 錯誤後產生的。緩衝區溢出。
請問您可以添加一個關於上下文切換建議的參考嗎?雖然我可以描繪處理器移動累加器數據並丟棄位,但這種機制對我來說似乎不是一個好的解釋,而更多細節可能會很有趣。 – 2011-02-15 19:42:23
也許使用不同的編譯器優化標誌可能會解決這個問題。 – tkerwin 2011-02-15 19:42:52
@火星上的咖啡:這是我的建議,所以我想我可以解釋:)問題是,FPU可以在寄存器中使用更多的位,在一些最新的處理器中可以使用多達80位雙打。現在,在單線程環境中,FPU將能夠以這種精度執行所有操作,並且您將得到一個結果。如果將其他線程/進程添加到混合中,則當OS執行上下文切換時,必須將64位雙精度寄存器的值存儲爲64位雙精度值。 – 2011-02-15 19:52:31