Intel, AMD及VIA CPU的微架构(10)

4.3.      将复杂指令分解为更简单的指令

你可以分解读/修改以及读/修改/写指令来改进成对性。例如:

;Example 4.10a. P1/PMMX Imperfect pairing

add[mem1], eax

add[mem2], ebx

这个代码可以分解为一个序列,将时钟周期从5降到3:

;Example 4.10b. P1/PMMX Imperfect pairing avoided

movecx, [mem1]

movedx, [mem2]

addecx, eax

addedx, ebx

mov[mem1], ecx

mov[mem2], edx

类似的,你可以将不可成对指令分解为可成对指令:

;Example 4.11a. P1/PMMX Non-pairable instructions

push[mem1]

push[mem2] ; Non-pairable

分解为:

;Example 4.11b. Split nonpairable instructions into pairable ones

moveax, [mem1]

movebx, [mem2]

pusheax

pushebx ; Everything pairs

另一个非可成对指令可以分解为更简单、可成对指令的例子:

;Example 4.12. P1/PMMX Split non-pairable instructions

CDQsplit into: mov edx, eax / sar edx,31

noteax change to xor eax, -1

negeax split into xor eax, -1 / inc eax

movzxeax, byte ptr [mem] split into xor eax, eax / mov al, byte ptr [mem]

jecxzL1 split into test ecx, ecx / jz L1

loopL1 split into dec ecx, / jnz L1

xlatchange to mov al, [ebx+eax]

如果分解指令没有改进速度,你可以保留复杂的或不可成对指令,以减小代码大小。在更新的处理器上,不需要指令分解,除非指令分解产生更少的μops。

4.4.      前缀

带有一个或更多前缀的指令可能不能在V-管道中执行,它可能需要多个时钟周期来解码。

在P1上,每个前缀的解码时延是1时钟周期,除了条件近程跳转前缀0FH。

对0FH前缀,PMMX没有解码时延。段与重复前缀需要1个额外时钟周期来解码。地址与操作数大小前缀需要两个额外周期来解码。每时钟周期PMMX可以解码两条指令,如果第一条指令有一个段或重复前缀,或者没有前缀,第二条指令没有前缀。带有地址或操作数大小前缀的指令仅可以单独在PMMX上解码。带有多个前缀的指令,每个前缀需要1个额外时钟周期。

在前缀不可避免时,解码时延可能被掩盖,如果前接的指令需要多个时钟周期来执行。对P1来说,规则是:任何需要N时钟周期来执行(不是解码)的指令,可以掩蔽下两条(有时三条)指令或指令对的N-1个前缀的时延。换而言之,指令执行所需的每个额外时钟周期可用于解码一条后续指令中的一个前缀。这个掩蔽效果甚至扩展到一个被预测的分支。任何需要多个时钟周期来执行的指令,以及任何由于AGI暂停、缓存不命中、未对齐,或者其他原因,除了解码时延及分支误预测,而延迟的指令,都有这样一个掩蔽影响。

PMMX有一个类似的掩蔽效果,但机制不同。已解码指令被保存在一个透明的,可以保存最多4条指令的先进先出(FIFO)缓冲。当这个缓冲是空的时候,指令一解码就得到执行。如果指令的解码比执行快,缓冲被填充,即当你有不成对或多周期指令时。在指令执行比解码快时,FIFO缓冲被清空,即由于前缀导致的解码时延。在一个误预测分支之后,FIFO缓冲被清空。FIFO缓冲每周期可以接受2条指令,只要第二条指令没有前缀,且指令都不超过7个字节。两条执行流水线(U与V)每个每周期可以从FIFO缓冲接受一条指令。例如:

;Example 4.13. P1/PMMX Overshadow prefix decoding delay

cld

repmovsd

CLD指令需要2个时钟周期,因此可以掩蔽REP前缀的解码时延。如果CLD指令远离REPMOVSD,代码还需要多一个时钟周期。

;Example 4.14. P1 Overshadow prefix decoding delay

cmpdword ptr [ebx], 0

moveax, 0

setnzal

这里CMP指令需要2个时钟周期,因为它是一条读/修改指令。SETNZ指令的0FH前缀在CMP指令的第2个时钟周期期间解码,使得在P1上解码时延被隐藏(PMMX对0FH没有解码时延)。

4.5.      浮点代码调度

浮点指令不能以整形指令的方式成对,除了一个由下面规则定义的特殊情形:

·        第一条指令(执行在U-管道中)必须是FLD,FADD,FSUB,FMUL,FDIV,FCOM,FCHS或FABS。

·        第二条指令(在V-管道中)必须是FXCH。

·        跟在FXCH后的指令必须是一条浮点指令,否则FXCH将不完美成对,需要一个额外时钟周期。

这个特殊成对是重要的,下面很快会解释。

尽管通常浮点指令不能成对,许多可以被流水线化,即一条指令可以在前面指令完成之前开始。例如:

;Example 4.15. Pipelined floating point instructions

faddst(1), st(0) ; Clock cycle 1-3

faddst(2), st(0) ; Clock cycle 2-4

faddst(3), st(0) ; Clock cycle 3-5

faddst(4), st(0) ; Clock cycle 4-6

显然,如果第二条指令需要第一条指令的结果,这两条指令不能重叠。因为几乎所有的浮点指令都涉及栈寄存器顶,ST(0),看起来使得一条指令与前面指令的结果无关,可能性不大。这个问题的解决方案是寄存器重命名。FXCH指令实际上没有交换两个寄存器的内容:它仅交换了它们的名字。压入或弹出寄存器栈的指令也通过重命名工作。在Pentium上,浮点寄存器重命名已经被高度优化,使得一个寄存器可以在使用的同时被重命名。寄存器重命名从来不会导致暂停——在同一个时钟周期里甚至多次重命名一个寄存器也是可能的,比如当FLD或FCOMPP与FXCH成对时。

通过正确使用FXCH指令,在浮点代码中可以获得许多重叠。指令FADD,FSUB,FMUL及FILD各个版本都需要3个时钟周期且能够重叠,因此这些指令能被调度。如果内存操作数在1级缓存且正确地对齐,使用内存操作数不会比寄存器操作数的时间更多。

现在你必须习惯带有例外的规则,重叠规则也不例外:你不能在另一条FMUL后1周期开始一条FMUL指令,因为FMUL电路不是完全流水线化的。建议在两条FMUL之间放置其他指令。例如:

;Example 4.16a. Floating point code with stalls

fld[a1]      ; Clock cycle 1

fld[b1]      ; Clock cycle 2

fld[c1]       ; Clock cycle 3

fxchst(2)   ; Clock cycle 3

fmul[a2]   ; Clock cycle 4-6

fxchst(1)   ; Clock cycle 4

fmul[b2]   ; Clock cycle 5-7 (stall)

fxchst(2)   ; Clock cycle 5

fmul[c2]   ; Clock cycle 7-9 (stall)

fxchst(1)   ; Clock cycle 7

fstp[a3]     ; Clock cycle 8-9

fxchst(1)   ; Clock cycle 10 (unpaired)

fstp[b3]    ; Clock cycle 11-12

fstp[c3]     ; Clock cycle 13-14

这里,在FMUL[b2]及MUL[c2]之前有一个暂停,因为另一个FMUL在前接时钟周期里开始。你可以通过在FMUL之间放置FLD指令来改进这个代码:

;Example 4.16b. Floating point stalls filled with other instructions

fld[a1]        ; Clock cycle 1

fmul[a2]     ; Clock cycle 2-4

fld[b1]         ; Clock cycle 3

fmul[b2]     ; Clock cycle 4-6

fld[c1]         ; Clock cycle 5

fmul[c2]      ; Clock cycle 6-8

fxchst(2)     ; Clock cycle 6

fstp[a3]       ; Clock cycle 7-8

fstp[b3]       ; Clock cycle 9-10

fstp[c3]       ; Clock cycle 11-12

在其他情形里,你可以将FADD,FSUB或其他别的,放在FMUL之间来避免暂停。不是所有的浮点指令都可以重叠。某些浮点指令比后续指令相比,可以与更多后续指令重叠。例如,FDIV指令需要39个时钟周期。除了第一个时钟周期,其他都可与整形指令重叠,但仅最后两个时钟周期可与浮点指令重叠。一个完整的浮点指令列表,以及它们可以与谁成对或重叠,在手册4:“指令表”里给出。

在浮点指令上使用内存操作数没有惩罚,因为在流水线中,算术单元比读单元晚一个阶段。在将一个浮点值保存到内存时,出现这个折衷。带有一个内存操作数的FST或FSTP指令在执行阶段需要两个时钟周期,但它需要数据早一个时钟周期就绪,因此如果要保存的值没有在一个时钟周期前准备好,你将得到一个时钟的暂停。这类似于AGI暂停。在许多情形里,不把浮点代码调度为4个线程,或在中间插入一些整形指令,你不能掩蔽这种类型的暂停。FSP(P)指令执行阶段的这两个时钟周期不能与任何后续指令成对或重叠。

带有整型操作数的指令,比如FIADD,FISUB,FIMUL,FIDIV,FICOM,可以分解为更简单的操作,以促进重叠。例如:

;Example 4.17a. Floating point code with integer operands

fild[a]

fimul[b]

分解为:

;Example 4.17b. Overlapping integer operations

fild[a]

fild[b]

fmul

在这个例子中,通过重叠两条FILD指令,我们节省了两个时钟周期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值