2

标题可能有点不清楚,所以在这里澄清一下:

问题:

a = b + c * d;

在我的实现中解决了这两个“指令”

mul(c, d, temp)
add(b, temp, a)

我目前正在使用临时对象来存储临时值,这要求将临时值存储在 RAM 中并在需要时再次获取它,这两者都不是真正需要的并且性能较低。

我正在用 C++ 实现 VM,所以我的问题是是否有一些可移植的方法来避免将临时值存储到主内存中,但将它们保存在实际的 CPU 寄存器中?

我已经使用register关键字进行了一些测试,但是从性能改进的不足来看,我会说编译器忽略了它。

作为最后的手段,我愿意进行平台特定的组装,但我对这个主题几乎一无所知,所以如果这是唯一可能的方法,欢迎提供好信息。我确实意识到我给出的这个例子是一个基本的例子,它很可能会遇到需要大量临时对象的情况,在这种情况下应该有一些方法来确定要使用和使用多少寄存器其余的内存存储...

也许有一些方法可以要求寄存器存储,如果编译器“用完”寄存器,自动将临时压入堆栈?就我对汇编的熟悉程度而言,您可以通过名称“寻址”特定寄存器,而我不清楚编译器究竟如何处理潜在的寄存器使用冲突......

4

4 回答 4

3

就像它一样inlineregister只是对编译器的建议。它可能会或可能不会跟随它,以及它可能会或可能不会将“正常”变量存储为变量register

C++ 标准说(7.1.1,第 3 段):

寄存器说明符是对实现的提示,即如此声明的变量将被大量使用。[ 注意:提示可以被忽略,并且在大多数实现中,如果变量的地址被获取,它将被忽略。这种用法已被弃用(见 D.2)。——尾注]

在进行这种低级优化之前,您应该真正运行良好的分析以确定系统的瓶颈,看看您是否真的需要它。

另外,我敢打赌,如果你不是专业的 asm 程序员,编译器会比你更好地优化代码(没有冒犯任何人,我的意思是一般意义上的)。

于 2012-08-09T09:17:37.460 回答
2

无论如何,寄存器不会像您认为的那样起作用。名称R2与地址并没有真正的不同2。当然,x86 程序集有更高级的名称,例如ECX,但这仍然是寄存器 2。

而且它们通常也不是物理的。像虚拟内存一样,寄存器名称是短暂的。现代处理器可能需要一段时间才能将寄存器值存储到 RAM。他们可以在回收寄存器之前等待它完成,但更快的解决方案是只回收名称并让旧的(现在未命名的)寄存器保持值直到写入完成。这意味着寄存器地址的数量可以低于物理寄存器的数量。(另一个好处是更新和更昂贵的 CPU 可以有更多的寄存器并且仍然与 ISA 兼容)。

也就是说,您的问题经典地解决了FMA- 融合乘法和加法。您的源代码不应转换为muland add,而应转换为mul_add(c,d,b,a). 这将允许 C++ 编译器发出 FMA 指令,完全绕过临时的需要。

于 2012-08-09T09:55:51.653 回答
2

C 没有为您提供任何方法来控制函数调用之间是否将值保存在寄存器中。

您正在尝试优化错误的东西。解析字符串和执行仿真所需的操作将涉及许多低级处理器操作,例如加载字节、比较字节并在表中查找它们、根据比较结果进行分支、将例程参数压入堆栈、从例程,在符号表中查找标识符等等。从内存中简单地加载一个值只是这个过程的一小部分。

即使假设您已经分离了解析和仿真,因此解析生成了虚拟机语言中的代码,执行该代码所需的操作仍然涉及许多操作,例如从内存中加载指令的字节,解码这些字节,分支到代码以执行解码的指令,依此类推。

在用 C 或 C++ 或任何高级语言编写时,您可能希望的最好的结果是在一个编译单元(一个源文件加上它包含的头文件)中编写所有仿真代码,甚至可能在一个例程中,所以编译器的优化器可以看到所有这些并对其进行优化。在这种情况下,如果您有一个正在读取、解码和执行指令的主循环,编译器可能会看到临时值中的值被保留并在迭代之间重复使用,因此编译器可能决定将这些临时值存储在寄存器中.

但是,模拟虚拟机是一项大型任务,因此您的代码可能有很多很多的对象。对于仿真机器中的每个寄存器,它将至少有一个对象(可能是一个数组元素),加上机器状态其他方面的对象,以及用于解码指令和调度仿真代码的对象。最简单的虚拟机模拟器,仅适用于课堂练习,可能有足够少的对象,它们中的大多数都适合处理器寄存器。但是任何稍微逼真的虚拟机模拟器都会有太多的对象,以至于它们中的很少一部分可以保留在处理器寄存器中。在这种情况下,您最好将优化留给优化器,而不是自己尝试。

于 2012-08-09T10:46:38.297 回答
0

如果在编译时打开优化,如果有足够的可用寄存器,编译器应该自动为局部变量使用寄存器。检查生成的机器代码,看看你的情况是否如此。

于 2012-08-09T09:28:49.477 回答