大会 – repz ret:为什么所有的麻烦?

这里[ 1]以及其他来源[ 2, 3]非常令人满意地讨论了repz ret的问题.但是,阅读这两个来源,我找到了以下答案:

>与ret或nop进行定量比较时的实际罚分是多少;沤?特别是在后一种情况下 – 当大多数函数有100个或者内联时,正在解码一个额外的指令(和那个空的!)真正相关吗?
>为什么这个从未在AMD K8中得到修复,甚至进入K10?从什么时候开始记录一个丑陋的变通方法,基于一种行为并且保持无证,优先考虑实际修复问题,何时知道原因的每个细节?

分支错误预测
所有喧闹的原因是分支误预测的成本.
当分支出现时,CPU会预测分支,并在管道中预加载这些指令.
如果预测错误,则需要清除管道并加载新指令.
这可能需要number_of_stages_in_pipeline周期以及从缓存加载数据所需的任何周期.每次误预测通常为14到25个周期.

原因:处理器设计
K8和K10之所以受此影响,是因为AMD的优化.
AMD K8和K10将对高速缓存中的指令进行预解码,并在CPU L1指令高速缓存中跟踪它们的长度.
为了做到这一点,它有额外的位.

For every 128 bits (16 bytes) of instructions there are 76 bits of additional data stored.

下表详细说明了这一点:

Data             Size       Notes
-------------------------------------------------------------------------
Instructions     128 bits   The data as read from memory
Parity bits      8 bits     One parity bit for every 16 bits
Pre-decode       56 bits    3 bits per byte (start, end, function) 
                            + 4 bit per 16 byte line
Branch selectors 16 bits    2 bits for each 2 bytes of instruction code

Total            204 bits   128 instructions, 76 metadata

因为所有这些数据都存储在L1指令缓存中,所以K8 / 10 cpu在解码和分支预测上的工作量要少得多.这节省了硅.
而且由于AMD没有像英特尔那样大的晶体管预算,因此需要更智能地工作.

但是,如果代码是esp.一个跳跃和一个ret可能占据相同的两个字节的槽,这意味着RET被预测为未被采用(因为跟随它的跳转).
通过使RET占用两个字节REP RET,这种情况永远不会发生,并且RET将始终被预测为OK.

英特尔没有这个问题,但(曾经)遭受过有限数量的预测时段,而AMD则没有.

nop ret
没有理由做nop ret.这是两个指令浪费额外的周期来执行nop并且ret可能仍然与跳跃“配对”.
如果要对齐使用REP MOV或使用多字节nop.

闭幕致辞只有本地分支预测与缓存中的指令一起存储.还有一个单独的全局分支预测表.

相关文章
相关标签/搜索