在每个平台上使用相同的模拟,具有正确的编译器标志

Same simulation on every platform with correct compiler flags

本文关键字:模拟 标志 编译器 平台      更新时间:2023-10-16

我开发游戏Remnants of Naezith大约2.5年,这个游戏的支柱是有重播排行榜。游戏是完全确定性的,因此相同的输入每次都会导致相同的模拟。 游戏完全是从头开始编写的C++和SFML。

几个月前,我将 gcc 编译器从 64 位更改为 32 位或反向,我记错了,但问题是,旧的重播在新编译器中不起作用。当我搜索它时,浮点数学在两者之间是不同的。

我通过放置 -msse2 -mfpmath=sse来修复它。然后它的工作原理相同。

今天我在调试模式下编译并运行了游戏,我第一次看到一些重播再次不同步。当我搜索它时,它是由我在发布版本中使用的-Ofast标志引起的。因为-Ofast标志中有 -ffast-math。这在计算中会有所不同,因此模拟也有所不同。

目前使用此-Ofast标志不会引起任何问题,因为每个人都在具有该标志的构建中玩游戏。

将来我想将我的游戏移植到Mac,Linux,PS4,Xbox或其他东西。我的排行榜位于我自己的服务器上,因此我想使用为所有平台共享的相同排行榜。这就是为什么我需要游戏在每个平台上都能完全相同地工作。

我的怀疑是,如果我保留这个-Ofast,每个人都会玩它,当我需要将我的游戏移植到另一个平台时,我可能需要更改我的编译器,并且该编译器可能没有相同的标志,或者数学在该编译器中的工作方式可能不同。

我应该避免哪些标志,我应该选择哪些标志,以确保它将模拟相同的重播,在每个平台上都相同

编辑:避免-Ofast摆脱-ffast-math听起来很明显,但我应该使用什么,之后会好吗?

这将很难实现。

当然,如果您的目标是 32 位和 64 位 x86/amd64 架构,您希望同时使用 SSE,否则在 32 位 x86 上,您最终可能会使用 x87,这肯定会造成差异。

即使你可以消除自己编译的代码中的任何差异,你也可能在标准库中遇到差异。例如,我在 FreeBSD/Solaris 和 Linux 之间 std::p ow() 的实现上遇到了差异。

我想使用定点表示是不可能的吗?