Alt-F4 #52 - 流体电力基准测试  2021-11-12

作者 stringweasel, 编辑 Nanogamer7, Conor_, Therenas, Firerazer, MyNameIsTrez,
翻译 Ph.X

目录

第 52 期,stringweasel 继续他的流体电力实验第二部分,深入研究了他的作品带来的奇妙性能影响。如果你喜欢上周的文章,那你也会喜欢本周的第二部分。想不到吧!

流体电力实验:第二部分 stringweasel

是什么来着?

上周的文章中,我谈到了异星工厂电网大改 Mod 的历史及工作机制,并讲解了我自己的实现,名为流体电力。建议先阅读那篇文章,但简而言之,我通过使用内置的流体模拟机制来让异星工厂的配电变得更加真实。这意味着你需要使用变压器来减少长距离输电带来的电压下降。这也意味着,比方说,要维持你的激光炮塔 100% 射速,或者建立大量插件效果分享塔覆盖的设施,都需要进行更多的工作。

一个在打开“show-fluid-box-info”情况下虫群攻击前哨的例子。绿色的是液位,蓝色的是液速。注意激光炮塔会间歇性地关闭。

这些新的限制意味着“流体电力”实现了其目标,即创造一个更贴近现实的新电力游戏机制。显然,它也引入了更多的性能开销,因为需要计算所有新的流体。我不希望把一个会导致你电脑带不动原先大小工厂的 Mod 放在 Mod 门户上。因此我开始做一些研究。这些额外的流体计算是否真的会带来重大影响?

其性能是否可玩?

异星工厂当前的电力模拟是有内在原因的。它允许我们建造超级巨大工厂,大到你会在其中迷路。添加更真实的电力可能会严重抑制性能,以至于你不得不建造更小的工厂,而没有人愿意这样做。所以问题是:如果有液体流过每根电线杆,异星工厂的性能究竟会变成什么样。我需要一张基准地图,在我的朋友 JanKrater 的帮助下,我开始建立一个纯流体电力基地。

我建造这个基地的方式是想出最高效的计划,然后做完全相反的操作(好吧,大部分如此)。由此得到一个有太多电线杆的意大利面条基地,非常复杂的传送带,以及太多高耗电的激光炮塔。但非常重要的是,它能稳定地每分钟生产 45 瓶,在无节能插件的情况下其功率大约为 600 MW。

以每分钟 45 瓶运行的基准意大利面基地。

通常情况下,异星工厂以每秒更新 60 次(简称 UPS)的速度运行,而我在我的老式 PC(i7-4770k 3.5GHz CPU,DDR3-1600MHz内存)上将这张基准地图成功地跑到了 70 UPS。这意味着,更新一次整个基地需要 ~14ms,称为一个 Tick,对于 60 UPS,每次更新的最大时间可以是 1/60 = ~16.6ms。这个数字也显示在下面的“show-time-usage”调试输出中。有趣的是,它还显示我的 Mod 脚本(mod-FluidicPower)对性能影响很小(~0.05ms)。这很正常因为我的 Mod 只做了很少的计算,它能够把所有昂贵的流体和电力计算卸载到高度优化的游戏引擎上。真正要看的主要时间信息是 Fluid Manager(流体管理)和 Electric Network(电网)。

45 SPM 意大利面基地的游戏内“show-time-usage”和“show-entity-time-usage”的信息。
45 SPM 意大利面基地的游戏内“show-time-usage”和“show-entity-time-usage”的信息。

在上面的输出中,游戏会告诉你时间大部分花在哪里了,起初令我感到困惑的是,游戏似乎把大部分时间花在 Electric Network 上。我本预期 Fluid Manager 会受到最大的性能冲击,但是输出显示 Electric Network~10ms)使用了 70% 以上的更新时间(~13.7ms),而 Fluid Manager~0.03ms)似乎根本没有做什么。这没有任何意义,因为我预计流体计算量会大量消耗性能。我去了异星工厂技术区社区,在那里他们把异星工厂的性能推到了极限。在这里,杰出的数学家 SteveTrov 向我解释了为什么在你不知道计时计算是如何实际实现时,游戏中的耗时情况会产生误导。他是这样描述的:

首先,耗时统计是混乱的,因为流体和电网络更新是在平行线程中运行的。以下是大多数时候会发生的情况:

  1. 电网线程被启动,电网更新计时器被启动。
  2. 热量线程被启动
  3. 多个流体更新线程被启动。
  4. 当电网更新进程完成时其耗时记录在电网更新下。流体更新计时器此时开始生效。
  5. 当流体线程全部完成后(通常在步骤4之前完成),流体更新计时器停止。

这样做的结果是,流体的更新时间几乎总是很低。

Firstly, the time usage stats are confusing because the fluid and electric network update are run in parallel threads. This is roughly what happens most of the time:

  1. The electric network thread is started and the electric network update timer is started.
  2. The heat update thread is stated
  3. Multiple fluid update threads are started.
  4. When the electric update thread finishes the time used is recorded under electric network update. The fluid update timer is effectively started now.
  5. When the fluid threads have all finished (they normally do before step 4) the fluid update timer is stopped.

So the effect of this is that the fluid update time is nearly always very low.

SteveTrov

这基本上意味着流体管理器的耗时信息与电网和热管理器的耗时纠缠在一起。在不改变异星工厂游戏引擎本身的情况下,不可能计算出一个准确的指标,即哪一部分占用了最多的处理时间。我需要另一种方法来知道 Electric Network 是否真的比 Fluid Manager 占用更多的处理时间,如果是的话又多多少?

一位名叫 flam_Sla 的 UPS 专家随后建议我下载 Very Sleepy Profiler,看看异星工厂引擎的哪些 C++ 函数被调用得最频繁的详细信息。他们的社区经常使用这个工具来优化世界上最大和最 UPS 高效的巨型基地。在下面这个工具的输出中,你可以看到哪些 C++ 函数花费的时间最多,按降序排列。flame_Sla 还提到不要关注显示的绝对时间,而是把它作为一个可以识别罪魁祸首的指标。

在我的意大利面流体电力基准测试基地上运行的 Very Sleepy 剖析工具的输出。右边是所选函数的调用栈的一个实例。
在我的意大利面流体电力基准测试基地上运行的 Very Sleepy 剖析工具的输出。右边是所选函数的调用栈的一个实例。

这显示了一些我未曾设想的东西。流体系统(FluidSystem::update)只位列耗时最久的前 10 个函数之中,而电网络仍然花费了更多的处理时间!事实证明,主要的问题是 FlowStatistics<ID<...>...>::onFlow,而这主要是由电网调用的。这些流量统计收集了查看游戏图表所需的数据,例如,电力生产窗口。这意味着游戏不仅因为所有新的流体计算而变慢,而且因为还要收集信息以绘制所有新的电网图而变慢!

最大的可能是,在流体电力下收集 Electric Network 统计数据可能需要大量的处理时间。异星工厂引擎被设计成只有少数几个电网,甚至只有一个。游戏需要为你的每一个电网收集和更新信息,通常只有几个不同的数据集。然而,流体电力的设计不是只有少数几个电网,而是 每一根 电线杆都是一个单一的电网。异星工厂引擎将尝试收集每个电网的统计数据——在我的基准存档中,大约有 3000 个电网!这至少是其设计容量的 100 倍。对一些其他 Mod 来说这是个已知的限制,但“流体电力”将其推向了一个新的极端。然而,我们仍然不知道这些计算的影响 相对 于流体计算而言。收集统计数据是否真的比流体计算本身要多花那么多时间?

flame_Sla 提到,他曾经设法测量了流体管理器在世界最大的巨型基地上的耗时情况,对于一个 40k SPM 60UPS 巨型基地,它只用了 ~0.4ms!这意味着只有 2.5% 的更新时间是花在流体计算上的!他将流体管理器的时间使用从电力网络中分离出来的方法是通过完全 消除 电力网络的测量。他通过将所有机器改为以木材为燃料运行来实现这一点,这意味着不再使用电力,电网也是空的。由于流体电力的工作原理,我不能轻易地以同样的方式消除电网的影响,而不同时减少流体管理器的负荷,但我可以反过来做!我可以删除所有的 流体 组件,用供应或消耗电力的 EEI 来代替它们。这将干净利落地消除所有额外的流体计算,同时确保工厂仍在正常运行没有消除电网的负荷。为了记录一个准确的、可比较的时间使用指标,我还试图强迫异星工厂在单核上运行。我运行了一个快速脚本,为这个测试替换了电杆的隐藏流体组件,结果如下:

  基准 修改后 差异
Electric Network 9.3ms 9.2ms 0.1ms
Heat Manager 0.03ms 0.03ms 0ms
Fluid Manager 0.13ms 0.08ms 0.05ms
Total 9.46ms 9.31ms 0.15ms
表中显示了未修改的基准与去除所有流体组件的修改后的时间结果对比。

这表明,在这个基准中,流体电力的 所有 额外流体计算只需要大约 ~0.15ms!这个数字可能仍然不是很准确,因为它在意大利面条基地的噪音范围内,测试并不理想,而且测量并行线程的时间是不准确的。然而,它确实给了我们一个很好的指示,说明大部分处理时间都去了哪里。这证明到目前为止,电网确实对性能有最大的影响,而额外的流体计算几乎可以忽略不计。这让人不禁要问,如果电力网络不进行不必要的统计收集,可以达到什么样的性能——也许我们会看到流体电力巨型基地,在核反应堆和大规模太阳能电池板阵列旁边修建巨大的变电站。

总而言之,流体电力的表现比我预期的要好得多。任何感知到的减速主要是由收集大量电网统计数据造成的,而不是流体计算本身。你仍可以发射火箭,并且不让你的 UPS 降到 60 以下。如果你有一个有效的布局,你甚至可以建造得更大一些(我已经在 220 UPS 的情况下实现了 90 SPM!),而且这个 Mod 不一定会像 Rseding1 预测的那样耗尽你的 UPS。幸运的是,异星工厂的设计和优化真的很好,即使没有按照预期运行。这证明了流体电力在性能上绝对是可玩的,但这并不是唯一重要的方面。

你该玩玩么?

就个人而言,我认为流体电力创造了一个非常有趣的挑战。如果你打算建立一个长寿的巨型基地,它可能不适合你,但如果你正在寻找一个有趣的冒险游戏与全新挑战,那么这个 Mod 可能正适合你。我非常喜欢克服它创造的所有新游戏障碍。例如,离你的蒸汽机最远的机器会首先关闭,这通常是你的煤矿上 为你的锅炉提供燃料 的电动采矿机。我以前从来没有经历过如此危险的煤矿死亡漩涡。或者,如果你用激光炮塔来保卫城墙时,你需要确保有足够的变压器以正确的电压供电。

然而,到目前为止,这个 Mod 我最喜欢的部分是知道有实际的电力流过电线杆。当你的基地拉动了太多的电力时,你甚至可以看到你的机器上有一波间歇性的断电,比如当许多激光炮塔同时发射时。这类似于我观察自己设计的电路时的感觉,因为知道电子在铜和硅中的流体般的运动。看着你复杂的传送带网络与电网一起工作来建造火箭的感觉,让工厂更具活力。你几乎可以看出它稳定的心跳,真的令人感到舒适。

征稿

一如既往的,我们正在召集任何想要为 Alt-F4 做出贡献的人,无论是提交文章还是帮助翻译都可以。如果您有些有趣的想法,并乐于与社区分享,这里就是一个好地方。如果您没有太大把握,我们会很乐意帮助您讨论内容创意和结构问题。如果您有意参与,从加入 Discord 开始吧!