有什么办法可以确保浮点运算结果在Linux和Windows中都是一样的 [英] Is there any way to make sure the floating point arithmetic result the same in both linux and windows

查看:461
本文介绍了有什么办法可以确保浮点运算结果在Linux和Windows中都是一样的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的程序在linux和windows上运行,我必须确保浮点运算在不同的操作系统中得到相同的结果。



这里是代码:

  for(int i = 0; i <100000; ++ i)
{
float d_value = 10.0f / float(i);
float p_value = 0.01f * float(i)+ 100.0f;
}

我使用 g ++ -m32 -c -static -g - O0 -ffloat-store 在linux中构建代码。
我使用/ fp:precise / O2在vs2005的窗口中构建代码。



当我printfd_value和p_value ,d_value在linux和windows中都是一样的。但是p_value有时是不同的。
例如,打印十六进制格式的p_value:

$ p code $ windows $ 42 b5d1eb
linux:42d5d1ec

为什么要这样做?

我的g ++版本是

$ p $ 配置为:../src/configure -v --with-pkgversion ='Debian 4.4.5- 8'--with-bugurl = file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages = c,c ++,fortran,objc,obj-c ++ --prefix = / usr - -program-suffix = -4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir = / usr / lib --without-included-gettext - enable-threads = posix --with-gxx-include-dir = / usr / include / c ++ / 4.4 --libdir = / usr / lib --enable -nls --enable-clocale = gnu --enable-libstdcxx-debug --enable-objc-gc --enable-targets = all --with-arch-32 = i586 --with-tune = generic --enable-checking = release --build = i486-linux-gnu --host = i486-linux-gnu -target = i486-linux-gnu
线程模型:posix
gcc版本4.4.5(Debian 4.4.5-8)

我使用标志 -ffloat-store ,因为这里有人的建议:


在Windows上使用 / fp:strict 来告诉编译器产生严格遵循IEEE 754的代码,和 gcc -msse2 -mfpmath = sse 在Linux上获取相同的行为。



你所看到的已经在StackOverflow上进行了讨论,但最好的调查是David Monniaux的文章。 / p>




使用 gcc -msse2 -mpfmath = sse 如下。指令 cvtsi2ssq divss mulss addss 是正确的使用说明,它们产生一个程序,其中 p_value 包含在一个点上 42d5d1ec

  .globl _main 
.align 4,0x90
_main:# #@main
.cfi_startproc
## BB#0:
pushq%rbp
Ltmp2:
.cfi_def_cfa_offset 16
Ltmp3:
。 cfi_offset%rbp,-16
movq%rsp,%rbp
Ltmp4:
.cfi_def_cfa_register%rbp
subq $ 32,%rsp
movl $ 0,-4(% rbp)
movl $ 0,-8(%rbp)
LBB0_1:## =>这个内部循环头:深度= 1
cmpl $ 100000,-8(%rbp)## imm = 0x186A0
jge LBB0_4
## BB#2:##在Loop:Header = BB0_1 Depth = 1
movq _p_value @ GOTPCREL(%rip),%rax
movabsq $ 100 ,%rcx
cvtsi 2ssq%rcx,%xmm0
movss LCPI0_0(%rip),%xmm1
movabsq $ 10,%rcx
cvtsi2ssq%rcx,%xmm2
cvtsi2ss -8(%rbp), %xmm3
divss%xmm3,%xmm2
movss%xmm2,-12(%rbp)
cvtsi2ss -8(%rbp),%xmm2
mulss%xmm2,%xmm1
addss%xmm0,%xmm1
movss%xmm1,(%rax)
movl(%rax),%edx
movl%edx,-16(%rbp)
leaq L_.str(%rip),%rdi
movl -16(%rbp),%esi
movb $ 0,%al
callq _printf
movl%eax, -20(%rbp)## 4字节溢出
## BB#3:##循环:Header = BB0_1 Depth = 1
movl -8(%rbp),%eax
addl $ 1,%eax
movl%eax,-8(%rbp)
jmp LBB0_1
LBB0_4:
movl -4(%rbp),%eax
addq $ 32,%rsp
popq%rbp
ret


My programe runs both in linux and windows, I have to make sure the floating point arithmetic get the same result in different OS.

Here is the code:

for (int i = 0; i < 100000; ++i)
{
    float d_value = 10.0f / float(i);
    float p_value = 0.01f * float(i) + 100.0f;
}

I use "g++ -m32 -c -static -g -O0 -ffloat-store" to build the code in linux. I use "/fp:precise /O2" to build the code in windows with vs2005.

When I printf the "d_value" and the "p_value", the "d_value" is all the same both in linux and windows. But the "p_value" is different sometimes. For exsample, print the "p_value" with hexadecimal format:

windows:  42d5d1eb
linux:    42d5d1ec

Why dose this happen?

My g++ version is

Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-8' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-targets=all --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.5 (Debian 4.4.5-8)

I use the flag -ffloat-store, because of someone's suggestion here: Different math rounding behaviour between Linux, Mac OS X and Windows

解决方案

Use /fp:strict on Windows to tell the compiler to produce code that strictly follows IEEE 754, and gcc -msse2 -mfpmath=sse on Linux to obtain the same behavior there.

The reasons for the differences you are seeing have been discussed in spots on StackOverflow, but the best survey is David Monniaux's article.


The assembly instructions I obtain when compiling with gcc -msse2 -mpfmath=sse are as follow. Instructions cvtsi2ssq, divss, mulss, addss are the correct instructions to use, and they result in a program where p_value contains at one point 42d5d1ec.

    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    subq    $32, %rsp
    movl    $0, -4(%rbp)
    movl    $0, -8(%rbp)
LBB0_1:                                 ## =>This Inner Loop Header: Depth=1
    cmpl    $100000, -8(%rbp)       ## imm = 0x186A0
    jge LBB0_4
## BB#2:                                ##   in Loop: Header=BB0_1 Depth=1
    movq    _p_value@GOTPCREL(%rip), %rax
    movabsq $100, %rcx
    cvtsi2ssq   %rcx, %xmm0
    movss   LCPI0_0(%rip), %xmm1
    movabsq $10, %rcx
    cvtsi2ssq   %rcx, %xmm2
    cvtsi2ss    -8(%rbp), %xmm3
    divss   %xmm3, %xmm2
    movss   %xmm2, -12(%rbp)
    cvtsi2ss    -8(%rbp), %xmm2
    mulss   %xmm2, %xmm1
    addss   %xmm0, %xmm1
    movss   %xmm1, (%rax)
    movl    (%rax), %edx
    movl    %edx, -16(%rbp)
    leaq    L_.str(%rip), %rdi
    movl    -16(%rbp), %esi
    movb    $0, %al
    callq   _printf
    movl    %eax, -20(%rbp)         ## 4-byte Spill
## BB#3:                                ##   in Loop: Header=BB0_1 Depth=1
    movl    -8(%rbp), %eax
    addl    $1, %eax
    movl    %eax, -8(%rbp)
    jmp LBB0_1
LBB0_4:
    movl    -4(%rbp), %eax
    addq    $32, %rsp
    popq    %rbp
    ret

这篇关于有什么办法可以确保浮点运算结果在Linux和Windows中都是一样的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆