计算机/游戏物理引擎为什么经常是非确定性的?

10
多年来,我使用了各种游戏物理引擎进行开发,我注意到在同一台计算机上,不同的物理模拟运行之间会有非常不同的结果。最近,Unity引擎就是如此,即使物理是按照固定时间间隔(FixedUpdate)计算的——据我所知,它应该是完全独立于帧速率的。
我之前在游戏论坛上问过这个问题,被告知这是由于混沌运动导致的: 请参见双摆。但是,即使是双摆如果初始条件完全控制,它也是确定性的,对吗? 在同一台机器上,浮点数运算不应该以相同的方式运作吗?
我知道浮点数精度存在问题,但我知道这些问题(如此处所述)在相同的硬件上不是问题——浮点数不精确仍然是确定性的吧?我漏掉了什么?
简而言之,如果在同一台计算机上运行模拟,并使用相同的浮点数运算,那么模拟不应是确定性的吗?
非常感谢您的时间。

@RyanVincent 浮点数确实是一种近似值,但它们仍然是确定性的,因此系统的混沌状态不应该有任何影响。 - pingul
值得注意的是,FixedUpdate() 不以一致的频率(Time.fixedTime)运行。更改间隔只会改变在 Update() 之前调用 FixedUpdate() 的次数(以“赶上”为目的),尽管具体数字取决于自上一帧以来经过的时间。这里有更多信息,可以了解实际发生的情况。 - Serlite
@Serlite 找到了相同的来源 :) 我已经根据此修改了我的答案。 - pingul
@RyanVincent 从这篇文章中可以看出:“...所以现在我们是否在所有编译器和机器上都有了确定性结果呢?不是。”(重点是我的)请注意,在同一台计算机上,结果将是相同的。 - pingul
2个回答

4

没错,你说得对。在同一台机器上执行的程序每次都会给出相同的结果(至少理论上是这样——可能会有宇宙射线或其他外部因素影响内存或其他方面,但我认为这些不是我们所关心的)。计算机上的所有计算都是确定性的,因此计算机的所有算法都必定是确定性的(这就是随机数生成器很难实现的原因)!

你看到的随机性很可能是通过某种随机数生成器在程序中实现的,并且用于随机数的种子在每次运行时都不同。如果你使用相同的种子开始模拟,你将会看到相同的结果。

编辑:我不熟悉Unity,但做更多的研究似乎表明FixedUpdate例程可能是问题所在。

除了音频线程外,如果您没有显式启动自己的线程,Unity 中的所有内容都在主线程中完成。 FixedUpdate 在完全相同的线程上运行,在与 Update 相同的间隔内运行,但它会弥补丢失的时间并模拟固定时间步骤。

来源

如果是这种情况,并且函数本身看起来有点像:

void physicsUpdate(double currentTime, double lastTime)
{
    double deltaT = currentTime - lastTime;
    // do physics using `deltaT`
}

在这里,由于两次运行中deltaT不同,我们会自然地得到不同的行为。这取决于后台运行的其他进程,它们可能会延迟主线程。该函数将不规则地被调用,您将观察到来自运行的不同结果。请注意,这些不规则性大多数情况下不是由于浮点不准确性引起,而是由于进行积分时的不准确性。(例如,速度通常通过v = a*deltaT计算,假设自上次更新以来加速度保持恒定。但这通常不是真实情况)。

然而,如果函数看起来像这样:

void physicsUpdate(double deltaT)
{
    // do physics using `deltaT`
}

每次使用它进行模拟,您都将获得完全相同的结果。

我认为你的修改是正确的答案。两次运行并不一定每个物理更新调用Time.deltaTime的值相同。对该值进行数学计算将导致小差异,随着时间的推移这些差异会累积。 - Scott Chamberlain
1
这对我来说似乎是最好的答案。我会继续深入探究为什么我使用过的每个游戏物理引擎都是非确定性的,但只是想要说一声感谢你花时间提供如此出色的答案!也许它们都有这个问题——固定更新可能有些难以实现? - Aaron Meier
是的,我无法找到Unity物理中任何故意随机的方面,因此我认为deltaT的变化更可能是问题所在。 - Aaron Meier
@ScottChamberlain 是的,我同意。一开始我不确定我们在谈论什么“非确定性”的事情。还应该注意的是,在这种情况下主要的差异不是由于浮点数不精确,而是由于线性积分误差引起的。 - pingul
我的印象是Unity的FixedUpdate例程是在类似于本帖中概述的例程中调用的(在这种情况下,变量deltatime不应该是不确定性的来源):http://www.kinematicsoup.com/news/2016/8/9/rrypp5tkubynjwxhxjzd42s3o034o8 - bitbutter
显示剩余5条评论

0

我对Unity或其物理模拟经验不多,但我找到了以下论坛帖子,其中还链接到一篇文章,似乎表明这取决于浮点计算的精度。

正如你所提到的,很多人似乎一直在重复这个问题!

该论坛还链接到这篇博客文章,可能会阐明这个问题。


浮点数运算是确定性的。在相同的输入情况下,你应该始终得到相同的输出结果。 - Chuu
谢谢你的回答,但是那些文章没有提到IEEE浮点数在相同硬件上有所不同...只是在不同的硬件上。浮点数应该在相同硬件上是确定性的...对吗? - Aaron Meier
@AaronMeier 我编辑问题链接到的博客文章似乎表明可能会有运行时因素影响它,所以很有可能! - Clint
2
@Clint - 可能是这样,但是randomascii的帖子没有提到相同的硬件,但它确实引用了这篇文章,特别提到了在不同硬件上浮点数的不确定性。 - Aaron Meier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接