Apple M1:负载和存储队列测量

2021-04-10 09:27:14

无序处理器必须立即跟踪多个飞行中的操作,并使用各种不同的缓冲区和队列来执行此操作。通过定时不同的指令模式,我一直在尝试在Apple M1处理器的Firestorm和Icestorm微体系结构中表征和测量其中一些缓冲区。

我测量了负载和存储队列的大小,发现当从调度程序发出OPS问题时分配负载和存储队列条目,并且一旦它们是非推测性的,并且都释放了所有早期的负载和存储。我也可能意外地发现了操纵载荷/商店别名预测的技巧。而且我认为我应该把它写起来,所以其他人可以重现它,和/或发现错误。

一般思想是在时间执行两个独立的长期操作(依赖指令的指令或链条),它们之间有许多负载或存储。通常,这两个长期操作可以并行运行,但如果有这么多的加载/存储某些缓冲区完全填充,则机器将失速,并且必须等到缓冲区中的空间被释放到执行后续指令。在亨利Wong的博客柱测量重新排序缓冲容量中首先描述了这种方法。

最初,在测量M1时,我使用缓存缺失的负载作为“两个独立的长期操作”(与其他人,我的知识一样)。

我的结果(非常大致看起来像Andtech的结果)是128负载或107家商店可以运行,而不停止并行执行的最终长期负载,但增加一个会导致摊位。由于第一负载,128个其他负载,并且最后一次负载同时在飞行中,我称之为130的负载队列大小。我仍然认为这是正确的。另一方面,负载不需要存储缓冲区,因此我不正确地称为107个条目商店队列。

虽然它不是本帖子的主题,但我还映射了调度队列和调度程序的结构:

如果OP可以输入调度程序,它可以留下调度程序并在所有依赖项准备好时执行。如果它可以进入调度队列,那么它将在有空间进入调度程序,直到那时,前端可以继续。但是如果调度程序和调度队列已满,我们有一个需要去那个队列的操作,我们摊位。这意味着在该队列中有空间,不会更多的操作可以进入任何调度队列。

值得注意的是,负载/商店调度程序有48个条目,具有10个条目调度队列。

(非常简单地:通过将调度器填充有一些负载或商店的调度程序来测量这些,根据第一个长期链,然后找到两个点。首先,我发现了独立负荷仍然适合的最后一点进入调度程序并运行,找到调度程序大小。然后,我发现额外的加载/存储的数量,一旦调度程序已满,就需要阻止独立的浮点操作。这给出了调度队列大小。混合操作使得可以弄清楚哪个调度员/队列是分开的,哪些是不可能的。我应该写这个吗?)

下一个想法是使用一系列长期浮点操作。令人惊讶的是,这产生了大约329个负载或商店可以在浮点操作之间运行,而不强调两个长期链接以平行完全运行。我假设这意味着在第一个长期链路退出之前,正在释放加载和存储队列条目,并重新使用,并且我们正在击中另一个限制。混合负载和存储确认它是相同的限制。 (这不是这篇文章的主题,但我已经探讨了一点并称为“聚结的退休队列”。我相信这是他们的抢夺实施。)

所以在这一点上,我猜测负载和商店可以完成(释放他们的加载/商店队列条目,而不是他们的退休队列条目)一旦它们是非投机性。我相信这次完成相对于其他负载和商店是按订单。我用于测试这一点的方法是具有单个,初始加载或存储操作,其地址取决于第一个长期操作的结果。

但是,对于此写作,我得到了相同的结果,而是通过依赖于第一个长期操作的结果来添加分支。这将确保负载和存储不能成为非投机性,并保持其队列条目。在此测试中,我们看到我们可以运行188个负载或118个商店,而无需强制两个长期链接才能并行运行。这最初是非常令人困惑的,因为我们相信我们只有130个入口加载缓冲区。那么,额外的58个参赛作品来自哪里?

Load / Store Scheduler有48个条目,具有10个条目调度队列。如果加载/存储调度程序和调度队列已满,则整数和浮点单元可以继续操作。但如果我们击中一个负载/商店,机器摊位,因为它无处可放置指示。这解释了58个额外条目。

通过此逻辑(为调度程序的大小和调度队列减去58),商店队列仅具有60个条目。那么为什么我们认为它有47个?因为如果48条目调度程序几乎已满,但具有一个自由条目,则负载可以输入调度程序,然后从调度程序发出(与其他长期负载并行),但如果计划程序完全完全,不能。

因此,这些是我当前的数字,130加载队列条目和60个商店队列条目。相同的逻辑适用于ICEStorm,在那里我们看到30个加载队列条目和18个商店队列条目(具有18个条目调度程序和6个条目调度队列)。

在为这篇文章写作时,我试图重现“107条目商店队列”的结果,但我得到的结果是60个条目。这既是最好的答案,我可以希望(这是我目前认为是正确的号码),以及最糟糕的结果(我写这件事,让人们可以重现我的工作,我没有重现我的工作自己的结果)。

所以出了什么问题?一点点,我发现这是由重构使用x29作为第二长延迟负载(具有可变偏移量)的基地址引起的,并且使用x29或sp作为商店的基地址(具有恒定的偏移) 。更改或两个寄存器返回x3(即使值没有改变)再次给我107。

处理器尝试从订单中执行加载并存储,这使得快速地使事物快速,只要在前面的(程序顺序“中的载重量稍后更改了由负载读取的数据。这称为违规的内存顺序。当它发生这种情况时,处理器通常会抛出所有工作并重新开始,这非常昂贵。 (Apple为此提供了一个性能计数器。它被称为Memory_Order_ViroAtion并被描述为“商店和依赖负载之间的错误猜测”。)因为这是如此昂贵,有预测器试图弄清楚负载和商店是否可能别名时按顺序运行它们。您可以阅读更多关于英特尔如何在Travis下降的“天窗写作的内存歧义”中如何接近Intel。

X29通常用作堆栈帧基指针,我怀疑内存依赖预测有一个特殊情况,并使负载等到它知道商店并不别名。该理论是,如果我们在负载前有60家投机商店,我们可以弄清楚所有地址,并且负载可以前进。但如果我们有61,我们无法检查最后一个,所以负载将等待。

我认为这种解释是有道理的,但这是一个令人惊讶的提醒,这里还有很多谜团在这里,它会进一步验证它。如果其他人想要调查这个问题,我将代码重现在一个GIST中。

所以,这是数据。要获得一个数字,我找到了跳跃的顶部(它是它完全串行执行的第一点)并减去一个。这是最大的指令数量比完全串行更快地执行可测量的金额。但是,你选择,结果足够接近。

(请注意,使用FCMP将依赖的B.CC一起链接,因为我认为FMOV可能会干扰内存操作。) 使用资源本身(负载+负载)测量之间的差异和使用其他资源(FSQRTS + LOADS)的测量在两个图中都非常清晰。 58指令差异意味着当我们没有资源执行更多加载时,我们可以继续将更多加载移动到调度程序中。 所以我得出结论,资源已迟到。 同样,我们可以击中〜330限制意味着这种资源可以早期释放。 在测量物理寄存器文件大小时 但是,我还没有理解了很多复杂性。