在计算机体系结构课程中,我了解到,在两个相互依赖的指令之间使用几个任意的、独立的nop指令可以防止数据的危害。在编译器设计中,这可以在程序集级别完成。
避免数据风险的另一种方法是使用数据转发。
我有点困惑,这两种选择在性能、速度和硬件方面有何不同。因为根据我的知识,数据转发将在硬件级别实现,而nop可以在组装级实现。
如果我们考虑到性能、速度、硬件等因素,请给我解释一下哪种方法更好?谢谢。
发布于 2014-02-15 17:50:13
显然,让编译器将nops插入到代码流中以填充管道槽,可以简化硬件,从而减少管道阶段的持续时间或管道的深度,减少设计工作量(上市时间、项目风险、设计成本),或者允许完整的处理器核心安装在单个芯片上(这有助于性能)。然而,与不使用转发造成的性能损失相比,这一好处非常小。对于典型的程序来说,依赖指令的延迟较高是非常糟糕的。
同时具有延迟分支和延迟负载的MIPS R2000提供了结果转发。(MIPS是“没有互锁流水线级的微处理器”的缩写。)。延迟加载很快从MIPS中删除(这是可能的,因为这不会影响正确代码的二进制兼容性)。延迟指令的使用部分是因为认为大多数延迟时隙可以由编译器用有用的指令填充,部分是因为认为增加代码大小对于简化硬件并不重要。
减少加载操作的延迟是不实际的,因此无论如何管道都需要停止循环。nop的代价是缓存和内存容量效应(即代码密度较低的影响),在某些情况下,可以填补单个负载延迟时隙。
公开管道组织对二进制兼容性也有影响。以后的二进制兼容实现必须适应为原始管道组织设计的ISA。单个延迟分支槽对于简单5级标量实现来说相当有效(大部分时间它可以被一个有用的指令所填充,并且允许零有效延迟分支,即不停止解决分支或预测,并在错误预测时冲洗管道),但是当管道被深化(或做得更广)时,预测或延迟仍然是必要的。
如果目标工作负载中存在足够的并行性,那么硬件简单性就足够重要,二进制兼容性也不是问题,那么公开一个支持动态检测和处理失速情况的最少支持的管道可能是明智的。(还有一些编码nops的方法可以避免大多数代码大小扩展问题。)具有可靠的足够的并行性(无论是指令级的还是线程级的)允许避免nops;通过使用指令级并行的编译器调度,或者通过硬件线程与线程级的并行。
硬件简单容易降低单位工作单位的能量(以及芯片面积),许多现代设计受到电源使用的限制。如果附加信息的存储和通信成本不太高(假设在编译时执行优化所必需的信息在编译时是可用的,动态分支预测是动态信息有用的典型例子),那么在编译时执行优化也是有意义的(当它们的延迟较小时,可以执行一次而不是每次执行代码)。
发布于 2018-06-13 16:29:44
嗯,基本上,由于硬件是优化的饲料转发,必须没有使用显式声明的软件NOPs。但事实并非如此。尽管饲料转发有助于减少数据风险,但一些风险无法通过饲料转发来处理。这是不可能的。
例如:
在此,在指令1完成其执行阶段并决定是否分支之前,将不会获取指令2。在此之前,第二条指令必须停止执行。(停滞了2个记忆周期)。这是通过软件发送NOPs来完成的。随着技术和硬件优化的改进,beq指令可以通过在取取阶段插入比较器来完成其寄存器取/解码阶段的执行阶段。即使如此,第二条指令将被暂停(现在是一个内存周期)。同样,NOP也是需要的。
https://stackoverflow.com/questions/21794659
复制相似问题