Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 若CPU是一个二进制机器,为什么它的位操作速度慢?_Performance_Assembly_X86_Bit_Cpu Architecture - Fatal编程技术网

Performance 若CPU是一个二进制机器,为什么它的位操作速度慢?

Performance 若CPU是一个二进制机器,为什么它的位操作速度慢?,performance,assembly,x86,bit,cpu-architecture,Performance,Assembly,X86,Bit,Cpu Architecture,我发现与二进制/双态性质相反,x86 CPU在处理诸如SHR、BT、BTR、ROL等二进制操作指令时非常慢 例如,我从某个地方读到,位移位/旋转超过1个位置被认为是缓慢的(具有高延迟、性能损失和那些可怕的东西)。当操作数在内存中时,情况更糟(难道内存不也是双状态外设吗?) 那么是什么让他们变慢了?具有讽刺意味的是,像CPU这样的二进制机器在进行位操作时速度很慢,而这种操作应该是自然的。它给人的印象是,二进制CPU的位移位很困难 编辑:现在,在再次查看手册中的SHL条目之后,它确实涉及一些重微码逻

我发现与二进制/双态性质相反,x86 CPU在处理诸如SHR、BT、BTR、ROL等二进制操作指令时非常慢

例如,我从某个地方读到,位移位/旋转超过1个位置被认为是缓慢的(具有高延迟、性能损失和那些可怕的东西)。当操作数在内存中时,情况更糟(难道内存不也是双状态外设吗?)

那么是什么让他们变慢了?具有讽刺意味的是,像CPU这样的二进制机器在进行位操作时速度很慢,而这种操作应该是自然的。它给人的印象是,二进制CPU的位移位很困难

编辑:现在,在再次查看手册中的SHL条目之后,它确实涉及一些重微码逻辑

操作
临时计数=计数&0x1F;
临时目的地=目的地;
while(临时计数!=0){
如果(指令==SAL | |指令==SHL){
CF=MSB(目的地);

Destination=Destination这只是指令的伪代码,精确地指定了它的功能。指令实际上并不是这样实现的。实际上,所有现代CPU都有桶形移位器或类似的移位器,允许它们在一个周期内移位任意量。例如,请参见其中显示alm的延迟为1ost所有位摆弄指令

少量的摆弄指令速度较慢,以下是一些示例:

  • bt
    btr
    bts
    btc
    与内存操作数一起使用时速度较慢,因为它们执行(a)读-修改-写操作和(b)位字符串索引
  • 旋转量大于
    1
    rcr
    速度较慢,因为几乎不需要该指令,因此未进行优化
  • pdep
    pext
    在Intel上稍慢一些,在AMD上则慢得多,这可能是因为它们的实现非常复杂,将实现拆分会更容易
在旧处理器上(例如8086),CPU将占用与移位量相同的周期,每个周期执行一次移位。这种实现允许ALU用于移位,而无需任何额外硬件,减少处理器所需的门的数量。据我所知,没有现代CPU具有这种性能行为。

只是一个说明

shl eax,1 ; opcode: d1 e0
shl eax,7 ; opcode: c1 e0 07

实际上是具有不同操作码的不同指令,这些指令可能由不同的ALU逻辑块处理。它们在汇编中使用相同的助记符,这可能会造成混淆,但从CPU的角度来看,它们是具有不同操作码和编码的不同指令。

芯片设计都是为了权衡。如果速度较慢在你的书中,这是因为其他一些东西被认为更值得在芯片上使用。编译器不使用
shl eax,1
,他们会使用
add eax,eax
,因为它同样短,可以在更多的执行端口上运行。有趣的事实:在英特尔CPU上,可变计数移位稍微慢一些:(英特尔Sandybridge系列上有3个UOP,如果在英特尔P6系列上使用标志结果,则可能会出现奇怪的暂停)。有关繁琐的x86语义的更多信息,请参阅。在这种语义中,如果计数=0,则立即计数或可变计数移位必须保留未修改的标志,因此指令需要依赖于旧标志。出于这个原因,一些汇编器将
shl eax
shl eax,1
区分开来。您能否提及它们的性能特征是否有所不同租金?(我想这对超标量CPU可能很重要?)问题的作者声称,在他的计算机上,它们的性能有很大的不同。他询问了原因。我只是强调了潜在的原因。从汇编程序的角度来看,这两条指令是完全不同的,这是完全不明显的。注意!要知道,指令执行的性能并不是一个简单的问题ISA规范的rt是处理器型号特定的!
bt
没有读-修改-写操作,对吗?(我认为这是一个输入错误?@user541686确实没有,但是(b)当然仍然适用。关于(b)对于
bt
,它是否比通常的替代方法(如
x&(1@user541686如果使用内存操作数,则为是。这是因为
bt
支持对位字符串进行索引并计算地址,这需要额外的周期。啊!明白了,谢谢!
Operation
TemporaryCount = Count & 0x1F;
TemporaryDestination = Destination;
while(TemporaryCount != 0) {
    if(Instruction == SAL || Instruction == SHL) {
        CF = MSB(Destination);
        Destination = Destination << 1;
    }
    //instruction is SAR or SHR
    else {
        CF = LSB(Destination);
        if(Instruction == SAR) Destination = Destination / 2; //Signed divide, rounding toward negative infinity
        //Instruction is SHR
        else Destination = Destination / 2; //Unsigned divide
    }
    TemporaryCount = TemporaryCount - 1;
}
//Determine overflow
if(Count & 0x1F == 1) {
    if(Instruction == SAL || Instruction == SHL) OF = MSB(Destination) ^ CF;
    else if(Instruction == SAR) OF = 0;
    //Instruction == SHR
    else OF = MSB(TemporaryDestination);
}
else OF = Undefined;
shl eax,1 ; opcode: d1 e0
shl eax,7 ; opcode: c1 e0 07