相关疑难解决方法(0)

浮点数学在C#中是否一致?是真的吗?

不,这不是另一个"为什么是(1/3.0)*3!= 1"的问题.

我最近一直在读关于漂浮点的事情; 具体而言,相同的计算如何在不同的体系结构或优化设置上给出不同的结果.

对于存储重放的视频游戏来说,这是一个问题,或者是对等网络(而不是服务器 - 客户端),它依赖于每次运行程序时产生完全相同结果的所有客户端 - 一个小的差异浮点计算可能导致不同机器(甚至是同一台机器上)的游戏状态截然不同!

甚至在"跟随" IEEE-754的处理器中也会发生这种情况,这主要是因为某些处理器(即x86)使用双倍扩展精度.也就是说,它们使用80位寄存器进行所有计算,然后截断为64位或32位,导致与使用64位或32位进行计算的机器不同的舍​​入结果.

我在网上看到过这个问题的几种解决方案,但都是针对C++,而不是C#:

  • double使用_controlfp_s(Windows),_FPU_SETCW(Linux?)或fpsetprec(BSD)禁用双扩展精度模式(以便所有计算使用IEEE-754 64位).
  • 始终使用相同的优化设置运行相同的编译器,并要求所有用户具有相同的CPU架构(无跨平台播放).因为我的"编译器"实际上是JIT,它可能在每次运行程序时都有不同的优化,我认为这是不可能的.
  • 使用定点算术,避免floatdouble完全.decimal可以用于此目的,但会慢得多,并且没有任何System.Math库函数支持它.

那么,这在C#中是否也是一个问题? 如果我只打算支持Windows(而不是Mono)怎么办?

如果是,有没有办法强制我的程序以正常的双精度运行?

如果没有,是否有任何库可以帮助保持浮点计算的一致性?

.net c# floating-point precision ieee-754

152
推荐指数
6
解决办法
1万
查看次数

浮点计算如何确定?

浮点计算既不是关联的,也不是处理器上的分配.所以,

(a + b) + c 不等于 a + (b + c)

a * (b + c)不等于a * b + a * c

有没有办法执行不会给出不同结果的确定性浮点计算.它对于单处理器来说是确定性的,但是如果线程增加一个总和,它在多线程程序中就不是确定性的,因为线程可能有不同的交错.

所以我的问题是,如何在多线程程序中实现浮点计算的确定性结果?

c deterministic

13
推荐指数
1
解决办法
4269
查看次数

跨平台浮点一致性

我正在开发一个使用锁步模型在网络上播放的跨平台游戏.作为简要概述,这意味着只传达输入,并且在每个客户端的计算机上模拟所有游戏逻辑.因此,一致性和决定性非常重要.

我正在编译使用GCC 4.8.1的MinGW32上的Windows版本,而在Linux上我正在使用GCC 4.8.2进行编译.

最近让我感到震惊的是,当我的Linux版本连接到我的Windows版本时,即使在两台机器上编译相同的代码,程序也会立即发生分歧或解除同步!原来问题是Linux构建是通过64位编译的,而Windows版本是32位.

在编译Linux 32位版本之后,我很幸运地解决了问题已经解决的问题.然而,它让我思考和研究浮点决定论.

这就是我收集的内容:

如果是,程序通常是一致的:

  • 在相同的架构上运行
  • 使用相同的编译器编译

因此,如果我假设,针对PC市场,每个人都有一个x86处理器,那么解决了一个要求.但是,第二个要求似乎有点傻.

MinGW,GCC和Clang(分别是Windows,Linux,Mac)都是基于/兼容GCC的不同编译器.这是否意味着实现跨平台决定论是不可能的?或者它只适用于Visual C++ vs GCC?

同样,优化标志-O1或-O2会影响这种决定论吗?让他们离开会更安全吗?

最后,我有三个问题要问:

  • 1)在编译器中使用MinGW,GCC和Clang时,跨平台确定性是否可行?
  • 2)应在这些编译器中设置哪些标志以确保操作系统/ CPU之间的最大一致性?
  • 3)浮点精度对我来说并不重要 - 重要的是它们是一致的.有没有任何方法可以将浮点数减少到较低的精度(如3-4个小数位),以确保跨系统的小圆整错误不存在?(到目前为止我尝试写的每个实现都失败了)

编辑:我做过一些跨平台的实验.

使用浮点数表示速度和位置,我保持Linux Intel笔记本电脑和Windows AMD台式电脑同步,最多可以浮动值的15位小数.但是,这两个系统都是x86_64.测试很简单 - 它只是通过网络移动实体,试图确定任何可见的错误.

如果x86计算机连接到x86_64计算机,假设相同的结果会成立是否有意义?(32位与64位操作系统)

c++ linux gcc

13
推荐指数
1
解决办法
4532
查看次数

SSE浮点运算是否可重复?

x87 FPU值得注意的是使用内部80位精度模式,这通常会导致编译器和机器出现意外和不可重现的结果.在我搜索 .NET上可重现的浮点数学时,我发现.NET(Microsoft和Mono)的两个主要实现都在64位模式下发出SSE指令而不是x87.

SSE(2)严格使用32位寄存器用于32位浮点数,严格使用64位寄存器用于64位浮点数.通过设置适当的控制字,可以选择将非正规数刷新为零.

因此,似乎SSE不会受到x87的精度相关问题的影响,并且唯一的变量是可以控制的非正规行为.

抛开超越函数的问题(SSE本身不像x87那样提供),是否使用SSE保证了机器和编译器之间可重现的结果?例如,编译器优化会转化为不同的结果吗?我发现了一些相互矛盾的观点:

如果您有SSE2,请使用它并从此过上幸福的生活.SSE2支持32b和64b操作,中间结果具有操作数的大小.- Yossi Kreinin,http://www.yosefk.com/blog/consistency-how-to-defeat-the-purpose-of-ieee-floating-point.html

...

SSE2指令(...)完全符合IEEE754-1985标准,它们具有更好的可重复性(由于静态舍入精度)和其他平台的可移植性.Muller et aliis, Handbook of Floating-Point Arithmetic - p.107

然而:

此外,您不能将SSE或SSE2用于浮点,因为它太低于指定而不具有确定性.- John Watte http://www.gamedev.net/topic/499435-floating-point-determinism/#entry4259411

.net floating-point sse ieee-754 x87

11
推荐指数
2
解决办法
2348
查看次数

在任何基于x86的体系结构中,是否有浮点密集型代码会产生位精确的结果?

我想知道在C或C ++中使用浮点运算的任何代码在任何基于x86的体系结构中是否都会产生精确的结果,而不管代码的复杂性如何。

据我所知,自从Intel 8087开始,任何x86架构都使用了准备处理IEEE-754浮点数的FPU单元,而且我看不出任何原因导致不同架构的结果不同。但是,如果它们不同(即由于不同的编译器或不同的优化级别),那么是否有某种方法可以通过仅配置编译器来产生位精确结果?

c x86 ieee-754 fast-math

5
推荐指数
1
解决办法
824
查看次数

标签 统计

ieee-754 ×3

.net ×2

c ×2

floating-point ×2

c# ×1

c++ ×1

deterministic ×1

fast-math ×1

gcc ×1

linux ×1

precision ×1

sse ×1

x86 ×1

x87 ×1